2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Rectangle;
27 import java.awt.Toolkit;
28 import java.awt.datatransfer.Clipboard;
29 import java.awt.datatransfer.DataFlavor;
30 import java.awt.datatransfer.StringSelection;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.dnd.DnDConstants;
33 import java.awt.dnd.DropTargetDragEvent;
34 import java.awt.dnd.DropTargetDropEvent;
35 import java.awt.dnd.DropTargetEvent;
36 import java.awt.dnd.DropTargetListener;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.awt.print.PageFormat;
47 import java.awt.print.PrinterJob;
48 import java.beans.PropertyChangeEvent;
50 import java.io.FileWriter;
51 import java.io.IOException;
52 import java.io.PrintWriter;
54 import java.util.ArrayList;
55 import java.util.Arrays;
56 import java.util.Deque;
57 import java.util.Enumeration;
58 import java.util.Hashtable;
59 import java.util.List;
60 import java.util.Locale;
61 import java.util.Vector;
62 import java.util.concurrent.Callable;
64 import javax.swing.ButtonGroup;
65 import javax.swing.JCheckBoxMenuItem;
66 import javax.swing.JComponent;
67 import javax.swing.JEditorPane;
68 import javax.swing.JInternalFrame;
69 import javax.swing.JLabel;
70 import javax.swing.JLayeredPane;
71 import javax.swing.JMenu;
72 import javax.swing.JMenuItem;
73 import javax.swing.JPanel;
74 import javax.swing.JScrollPane;
75 import javax.swing.SwingUtilities;
77 import ext.vamsas.ServiceHandle;
78 import jalview.analysis.AlignmentSorter;
79 import jalview.analysis.AlignmentUtils;
80 import jalview.analysis.CrossRef;
81 import jalview.analysis.Dna;
82 import jalview.analysis.GeneticCodeI;
83 import jalview.analysis.ParseProperties;
84 import jalview.analysis.SequenceIdMatcher;
85 import jalview.api.AlignExportSettingsI;
86 import jalview.api.AlignViewControllerGuiI;
87 import jalview.api.AlignViewControllerI;
88 import jalview.api.AlignViewportI;
89 import jalview.api.AlignmentViewPanel;
90 import jalview.api.FeatureSettingsControllerI;
91 import jalview.api.FeatureSettingsModelI;
92 import jalview.api.SplitContainerI;
93 import jalview.api.ViewStyleI;
94 import jalview.api.analysis.SimilarityParamsI;
95 import jalview.bin.Cache;
96 import jalview.bin.Console;
97 import jalview.bin.Jalview;
98 import jalview.commands.CommandI;
99 import jalview.commands.EditCommand;
100 import jalview.commands.EditCommand.Action;
101 import jalview.commands.OrderCommand;
102 import jalview.commands.RemoveGapColCommand;
103 import jalview.commands.RemoveGapsCommand;
104 import jalview.commands.SlideSequencesCommand;
105 import jalview.commands.TrimRegionCommand;
106 import jalview.datamodel.AlignExportSettingsAdapter;
107 import jalview.datamodel.AlignedCodonFrame;
108 import jalview.datamodel.Alignment;
109 import jalview.datamodel.AlignmentAnnotation;
110 import jalview.datamodel.AlignmentExportData;
111 import jalview.datamodel.AlignmentI;
112 import jalview.datamodel.AlignmentOrder;
113 import jalview.datamodel.AlignmentView;
114 import jalview.datamodel.ColumnSelection;
115 import jalview.datamodel.HiddenColumns;
116 import jalview.datamodel.PDBEntry;
117 import jalview.datamodel.SeqCigar;
118 import jalview.datamodel.Sequence;
119 import jalview.datamodel.SequenceGroup;
120 import jalview.datamodel.SequenceI;
121 import jalview.gui.ColourMenuHelper.ColourChangeListener;
122 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
123 import jalview.io.AlignmentProperties;
124 import jalview.io.AnnotationFile;
125 import jalview.io.BackupFiles;
126 import jalview.io.BioJsHTMLOutput;
127 import jalview.io.DataSourceType;
128 import jalview.io.FileFormat;
129 import jalview.io.FileFormatI;
130 import jalview.io.FileFormats;
131 import jalview.io.FileLoader;
132 import jalview.io.FileParse;
133 import jalview.io.FormatAdapter;
134 import jalview.io.HtmlSvgOutput;
135 import jalview.io.IdentifyFile;
136 import jalview.io.JPredFile;
137 import jalview.io.JalviewFileChooser;
138 import jalview.io.JalviewFileView;
139 import jalview.io.JnetAnnotationMaker;
140 import jalview.io.NewickFile;
141 import jalview.io.ScoreMatrixFile;
142 import jalview.io.TCoffeeScoreFile;
143 import jalview.io.vcf.VCFLoader;
144 import jalview.jbgui.GAlignFrame;
145 import jalview.project.Jalview2XML;
146 import jalview.schemes.ColourSchemeI;
147 import jalview.schemes.ColourSchemes;
148 import jalview.schemes.ResidueColourScheme;
149 import jalview.schemes.TCoffeeColourScheme;
150 import jalview.util.HttpUtils;
151 import jalview.util.ImageMaker.TYPE;
152 import jalview.util.MessageManager;
153 import jalview.util.Platform;
154 import jalview.util.imagemaker.BitmapImageSizing;
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() && progressBar != null)
986 progressBar.setProgressBar(message, id);
990 public void registerHandler(final long id,
991 final IProgressIndicatorHandler handler)
993 if (progressBar != null)
994 progressBar.registerHandler(id, handler);
999 * @return true if any progress bars are still active
1002 public boolean operationInProgress()
1004 return progressBar == null ? false : progressBar.operationInProgress();
1008 * Sets the text of the status bar. Note that setting a null or empty value
1009 * will cause the status bar to be hidden, with possibly undesirable flicker
1010 * of the screen layout.
1013 public void setStatus(String text)
1015 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1019 * Added so Castor Mapping file can obtain Jalview Version
1021 public String getVersion()
1023 return Cache.getProperty("VERSION");
1026 public FeatureRenderer getFeatureRenderer()
1028 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1032 public void fetchSequence_actionPerformed()
1034 new SequenceFetcher(this);
1038 public void addFromFile_actionPerformed(ActionEvent e)
1040 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1044 public void reload_actionPerformed(ActionEvent e)
1046 if (fileName != null)
1048 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1049 // originating file's format
1050 // TODO: work out how to recover feature settings for correct view(s) when
1051 // file is reloaded.
1052 if (FileFormat.Jalview.equals(currentFileFormat))
1054 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1055 for (int i = 0; i < frames.length; i++)
1057 if (frames[i] instanceof AlignFrame && frames[i] != this
1058 && ((AlignFrame) frames[i]).fileName != null
1059 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1063 frames[i].setSelected(true);
1064 Desktop.instance.closeAssociatedWindows();
1065 } catch (java.beans.PropertyVetoException ex)
1071 Desktop.instance.closeAssociatedWindows();
1073 FileLoader loader = new FileLoader();
1074 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1075 ? DataSourceType.URL
1076 : DataSourceType.FILE;
1077 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1081 Rectangle bounds = this.getBounds();
1083 FileLoader loader = new FileLoader();
1085 AlignFrame newframe = null;
1087 if (fileObject == null)
1090 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1091 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1092 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1097 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1098 DataSourceType.FILE, currentFileFormat);
1101 newframe.setBounds(bounds);
1102 if (featureSettings != null && featureSettings.isShowing())
1104 final Rectangle fspos = featureSettings.frame.getBounds();
1105 // TODO: need a 'show feature settings' function that takes bounds -
1106 // need to refactor Desktop.addFrame
1107 newframe.featureSettings_actionPerformed(null);
1108 final FeatureSettings nfs = newframe.featureSettings;
1109 SwingUtilities.invokeLater(new Runnable()
1114 nfs.frame.setBounds(fspos);
1117 this.featureSettings.close();
1118 this.featureSettings = null;
1120 this.closeMenuItem_actionPerformed(true);
1126 public void addFromText_actionPerformed(ActionEvent e)
1129 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1133 public void addFromURL_actionPerformed(ActionEvent e)
1135 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1139 public void save_actionPerformed(ActionEvent e)
1141 if (fileName == null || (currentFileFormat == null)
1142 || HttpUtils.startsWithHttpOrHttps(fileName))
1144 saveAs_actionPerformed();
1148 saveAlignment(fileName, currentFileFormat);
1153 * Saves the alignment to a file with a name chosen by the user, if necessary
1154 * warning if a file would be overwritten
1157 public void saveAs_actionPerformed()
1159 String format = currentFileFormat == null ? null
1160 : currentFileFormat.getName();
1161 JalviewFileChooser chooser = JalviewFileChooser
1162 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1164 chooser.setFileView(new JalviewFileView());
1165 chooser.setDialogTitle(
1166 MessageManager.getString("label.save_alignment_to_file"));
1167 chooser.setToolTipText(MessageManager.getString("action.save"));
1169 int value = chooser.showSaveDialog(this);
1171 if (value != JalviewFileChooser.APPROVE_OPTION)
1175 currentFileFormat = chooser.getSelectedFormat();
1176 // todo is this (2005) test now obsolete - value is never null?
1177 while (currentFileFormat == null)
1179 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1181 .getString("label.select_file_format_before_saving"),
1182 MessageManager.getString("label.file_format_not_specified"),
1183 JvOptionPane.WARNING_MESSAGE);
1184 currentFileFormat = chooser.getSelectedFormat();
1185 value = chooser.showSaveDialog(this);
1186 if (value != JalviewFileChooser.APPROVE_OPTION)
1192 fileName = chooser.getSelectedFile().getPath();
1194 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1195 Cache.setProperty("LAST_DIRECTORY", fileName);
1196 saveAlignment(fileName, currentFileFormat);
1199 boolean lastSaveSuccessful = false;
1201 FileFormatI lastFormatSaved;
1203 String lastFilenameSaved;
1206 * Raise a dialog or status message for the last call to saveAlignment.
1208 * @return true if last call to saveAlignment(file, format) was successful.
1210 public boolean isSaveAlignmentSuccessful()
1213 if (!lastSaveSuccessful)
1215 if (!Platform.isHeadless())
1217 JvOptionPane.showInternalMessageDialog(this, MessageManager
1218 .formatMessage("label.couldnt_save_file", new Object[]
1219 { lastFilenameSaved }),
1220 MessageManager.getString("label.error_saving_file"),
1221 JvOptionPane.WARNING_MESSAGE);
1225 Console.error(MessageManager
1226 .formatMessage("label.couldnt_save_file", new Object[]
1227 { lastFilenameSaved }));
1233 setStatus(MessageManager.formatMessage(
1234 "label.successfully_saved_to_file_in_format", new Object[]
1235 { lastFilenameSaved, lastFormatSaved }));
1238 return lastSaveSuccessful;
1242 * Saves the alignment to the specified file path, in the specified format,
1243 * which may be an alignment format, or Jalview project format. If the
1244 * alignment has hidden regions, or the format is one capable of including
1245 * non-sequence data (features, annotations, groups), then the user may be
1246 * prompted to specify what to include in the output.
1251 public void saveAlignment(String file, FileFormatI format)
1253 lastSaveSuccessful = true;
1254 lastFilenameSaved = file;
1255 lastFormatSaved = format;
1257 if (FileFormat.Jalview.equals(format))
1259 String shortName = title;
1260 if (shortName.indexOf(File.separatorChar) > -1)
1262 shortName = shortName
1263 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1265 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1268 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1269 if (lastSaveSuccessful)
1271 this.getViewport().setSavedUpToDate(true);
1274 statusBar.setText(MessageManager.formatMessage(
1275 "label.successfully_saved_to_file_in_format", new Object[]
1281 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1282 Callable<Void> cancelAction = () -> {
1283 lastSaveSuccessful = false;
1286 Callable<Void> outputAction = () -> {
1287 // todo defer this to inside formatSequences (or later)
1288 AlignmentExportData exportData = viewport.getAlignExportData(options);
1289 String output = new FormatAdapter(alignPanel, options)
1290 .formatSequences(format, exportData.getAlignment(),
1291 exportData.getOmitHidden(),
1292 exportData.getStartEndPostions(),
1293 viewport.getAlignment().getHiddenColumns());
1296 lastSaveSuccessful = false;
1300 // create backupfiles object and get new temp filename destination
1301 boolean doBackup = BackupFiles.getEnabled();
1302 BackupFiles backupfiles = null;
1305 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1306 backupfiles = new BackupFiles(file);
1310 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1312 Console.trace("ALIGNFRAME setting PrintWriter");
1313 PrintWriter out = new PrintWriter(new FileWriter(tempFilePath));
1315 if (backupfiles != null)
1317 Console.trace("ALIGNFRAME about to write to temp file "
1318 + backupfiles.getTempFilePath());
1322 Console.trace("ALIGNFRAME about to close file");
1324 Console.trace("ALIGNFRAME closed file");
1325 AlignFrame.this.setTitle(file);
1326 statusBar.setText(MessageManager.formatMessage(
1327 "label.successfully_saved_to_file_in_format", new Object[]
1328 { fileName, format.getName() }));
1329 lastSaveSuccessful = true;
1330 } catch (IOException e)
1332 lastSaveSuccessful = false;
1334 "ALIGNFRAME Something happened writing the temp file");
1335 Console.error(e.getMessage());
1336 Console.debug(Cache.getStackTraceString(e));
1337 } catch (Exception ex)
1339 lastSaveSuccessful = false;
1341 "ALIGNFRAME Something unexpected happened writing the temp file");
1342 Console.error(ex.getMessage());
1343 Console.debug(Cache.getStackTraceString(ex));
1348 backupfiles.setWriteSuccess(lastSaveSuccessful);
1349 Console.debug("ALIGNFRAME writing temp file was "
1350 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1351 // do the backup file roll and rename the temp file to actual file
1352 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1353 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1354 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1355 + (lastSaveSuccessful ? "" : "un") + "successfully");
1358 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1359 if (lastSaveSuccessful)
1361 AlignFrame.this.getViewport().setSavedUpToDate(true);
1368 * show dialog with export options if applicable; else just do it
1370 if (AlignExportOptions.isNeeded(viewport, format))
1372 AlignExportOptions choices = new AlignExportOptions(
1373 alignPanel.getAlignViewport(), format, options);
1374 choices.setResponseAction(0, outputAction);
1375 choices.setResponseAction(1, cancelAction);
1376 choices.showDialog();
1382 outputAction.call();
1383 } catch (Exception e)
1385 // TODO Auto-generated catch block
1386 e.printStackTrace();
1392 * Outputs the alignment to textbox in the requested format, if necessary
1393 * first prompting the user for whether to include hidden regions or
1396 * @param fileFormatName
1399 protected void outputText_actionPerformed(String fileFormatName)
1401 FileFormatI fileFormat = FileFormats.getInstance()
1402 .forName(fileFormatName);
1403 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1404 Callable<Void> outputAction = () -> {
1405 // todo defer this to inside formatSequences (or later)
1406 AlignmentExportData exportData = viewport.getAlignExportData(options);
1407 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1408 cap.setForInput(null);
1411 FileFormatI format = fileFormat;
1412 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1413 format, exportData.getAlignment(),
1414 exportData.getOmitHidden(),
1415 exportData.getStartEndPostions(),
1416 viewport.getAlignment().getHiddenColumns()));
1417 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1418 "label.alignment_output_command", new Object[]
1419 { fileFormat.getName() }), 600, 500);
1420 } catch (OutOfMemoryError oom)
1422 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1430 * show dialog with export options if applicable; else just do it
1432 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1434 AlignExportOptions choices = new AlignExportOptions(
1435 alignPanel.getAlignViewport(), fileFormat, options);
1436 choices.setResponseAction(0, outputAction);
1437 choices.showDialog();
1443 outputAction.call();
1444 } catch (Exception e)
1446 e.printStackTrace();
1458 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1460 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1461 htmlSVG.exportHTML(null);
1465 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1467 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1468 bjs.exportHTML(null);
1471 public void createImageMap(File file, String image)
1473 alignPanel.makePNGImageMap(file, image);
1477 * Creates a PNG image of the alignment and writes it to the given file. If
1478 * the file is null, the user is prompted to choose a file.
1483 public void createPNG(File f)
1485 createPNG(f, null, BitmapImageSizing.nullBitmapImageSizing());
1488 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1490 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1494 * Creates an EPS image of the alignment and writes it to the given file. If
1495 * the file is null, the user is prompted to choose a file.
1500 public void createEPS(File f)
1505 public void createEPS(File f, String renderer)
1507 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1511 * Creates an SVG image of the alignment and writes it to the given file. If
1512 * the file is null, the user is prompted to choose a file.
1517 public void createSVG(File f)
1522 public void createSVG(File f, String renderer)
1524 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1528 public void pageSetup_actionPerformed(ActionEvent e)
1530 PrinterJob printJob = PrinterJob.getPrinterJob();
1531 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1541 public void printMenuItem_actionPerformed(ActionEvent e)
1543 // Putting in a thread avoids Swing painting problems
1544 PrintThread thread = new PrintThread(alignPanel);
1549 public void exportFeatures_actionPerformed(ActionEvent e)
1551 new AnnotationExporter(alignPanel).exportFeatures();
1555 public void exportAnnotations_actionPerformed(ActionEvent e)
1557 new AnnotationExporter(alignPanel).exportAnnotations();
1561 public void associatedData_actionPerformed(ActionEvent e)
1563 final JalviewFileChooser chooser = new JalviewFileChooser(
1564 Cache.getProperty("LAST_DIRECTORY"));
1565 chooser.setFileView(new JalviewFileView());
1566 String tooltip = MessageManager
1567 .getString("label.load_jalview_annotations");
1568 chooser.setDialogTitle(tooltip);
1569 chooser.setToolTipText(tooltip);
1570 chooser.setResponseHandler(0, () -> {
1571 String choice = chooser.getSelectedFile().getPath();
1572 Cache.setProperty("LAST_DIRECTORY", choice);
1573 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1577 chooser.showOpenDialog(this);
1581 * Close the current view or all views in the alignment frame. If the frame
1582 * only contains one view then the alignment will be removed from memory.
1584 * @param closeAllTabs
1587 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1589 if (alignPanels != null && alignPanels.size() < 2)
1591 closeAllTabs = true;
1596 if (alignPanels != null)
1600 if (this.isClosed())
1602 // really close all the windows - otherwise wait till
1603 // setClosed(true) is called
1604 for (int i = 0; i < alignPanels.size(); i++)
1606 AlignmentPanel ap = alignPanels.get(i);
1613 closeView(alignPanel);
1618 if (featureSettings != null && featureSettings.isOpen())
1620 featureSettings.close();
1621 featureSettings = null;
1624 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1625 * be called recursively, with the frame now in 'closed' state
1627 this.setClosed(true);
1629 } catch (Exception ex)
1631 ex.printStackTrace();
1636 * Close the specified panel and close up tabs appropriately.
1638 * @param panelToClose
1640 public void closeView(AlignmentPanel panelToClose)
1642 int index = tabbedPane.getSelectedIndex();
1643 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1644 alignPanels.remove(panelToClose);
1645 panelToClose.closePanel();
1646 panelToClose = null;
1648 tabbedPane.removeTabAt(closedindex);
1649 tabbedPane.validate();
1651 if (index > closedindex || index == tabbedPane.getTabCount())
1653 // modify currently selected tab index if necessary.
1657 this.tabSelectionChanged(index);
1663 void updateEditMenuBar()
1666 if (viewport.getHistoryList().size() > 0)
1668 undoMenuItem.setEnabled(true);
1669 CommandI command = viewport.getHistoryList().peek();
1670 undoMenuItem.setText(MessageManager
1671 .formatMessage("label.undo_command", new Object[]
1672 { command.getDescription() }));
1676 undoMenuItem.setEnabled(false);
1677 undoMenuItem.setText(MessageManager.getString("action.undo"));
1680 if (viewport.getRedoList().size() > 0)
1682 redoMenuItem.setEnabled(true);
1684 CommandI command = viewport.getRedoList().peek();
1685 redoMenuItem.setText(MessageManager
1686 .formatMessage("label.redo_command", new Object[]
1687 { command.getDescription() }));
1691 redoMenuItem.setEnabled(false);
1692 redoMenuItem.setText(MessageManager.getString("action.redo"));
1697 public void addHistoryItem(CommandI command)
1699 if (command.getSize() > 0)
1701 viewport.addToHistoryList(command);
1702 viewport.clearRedoList();
1703 updateEditMenuBar();
1704 viewport.updateHiddenColumns();
1705 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1706 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1707 // viewport.getColumnSelection()
1708 // .getHiddenColumns().size() > 0);
1714 * @return alignment objects for all views
1716 AlignmentI[] getViewAlignments()
1718 if (alignPanels != null)
1720 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1722 for (AlignmentPanel ap : alignPanels)
1724 als[i++] = ap.av.getAlignment();
1728 if (viewport != null)
1730 return new AlignmentI[] { viewport.getAlignment() };
1742 protected void undoMenuItem_actionPerformed(ActionEvent e)
1744 if (viewport.getHistoryList().isEmpty())
1748 CommandI command = viewport.getHistoryList().pop();
1749 viewport.addToRedoList(command);
1750 command.undoCommand(getViewAlignments());
1752 AlignmentViewport originalSource = getOriginatingSource(command);
1753 updateEditMenuBar();
1755 if (originalSource != null)
1757 if (originalSource != viewport)
1760 "Implementation worry: mismatch of viewport origin for undo");
1762 originalSource.updateHiddenColumns();
1763 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1765 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1766 // viewport.getColumnSelection()
1767 // .getHiddenColumns().size() > 0);
1768 originalSource.firePropertyChange("alignment", null,
1769 originalSource.getAlignment().getSequences());
1780 protected void redoMenuItem_actionPerformed(ActionEvent e)
1782 if (viewport.getRedoList().size() < 1)
1787 CommandI command = viewport.getRedoList().pop();
1788 viewport.addToHistoryList(command);
1789 command.doCommand(getViewAlignments());
1791 AlignmentViewport originalSource = getOriginatingSource(command);
1792 updateEditMenuBar();
1794 if (originalSource != null)
1797 if (originalSource != viewport)
1800 "Implementation worry: mismatch of viewport origin for redo");
1802 originalSource.updateHiddenColumns();
1803 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1805 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1806 // viewport.getColumnSelection()
1807 // .getHiddenColumns().size() > 0);
1808 originalSource.firePropertyChange("alignment", null,
1809 originalSource.getAlignment().getSequences());
1813 AlignmentViewport getOriginatingSource(CommandI command)
1815 AlignmentViewport originalSource = null;
1816 // For sequence removal and addition, we need to fire
1817 // the property change event FROM the viewport where the
1818 // original alignment was altered
1819 AlignmentI al = null;
1820 if (command instanceof EditCommand)
1822 EditCommand editCommand = (EditCommand) command;
1823 al = editCommand.getAlignment();
1824 List<Component> comps = PaintRefresher.components
1825 .get(viewport.getSequenceSetId());
1827 for (Component comp : comps)
1829 if (comp instanceof AlignmentPanel)
1831 if (al == ((AlignmentPanel) comp).av.getAlignment())
1833 originalSource = ((AlignmentPanel) comp).av;
1840 if (originalSource == null)
1842 // The original view is closed, we must validate
1843 // the current view against the closed view first
1846 PaintRefresher.validateSequences(al, viewport.getAlignment());
1849 originalSource = viewport;
1852 return originalSource;
1856 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1857 * or the sequence under cursor in keyboard mode
1862 public void moveSelectedSequences(boolean up)
1864 SequenceGroup sg = viewport.getSelectionGroup();
1868 if (viewport.cursorMode)
1870 sg = new SequenceGroup();
1871 sg.addSequence(viewport.getAlignment().getSequenceAt(
1872 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1880 if (sg.getSize() < 1)
1885 // TODO: JAL-3733 - add an event to the undo buffer for this !
1887 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1888 viewport.getHiddenRepSequences(), up);
1889 alignPanel.paintAlignment(true, false);
1892 synchronized void slideSequences(boolean right, int size)
1894 List<SequenceI> sg = new ArrayList<>();
1895 if (viewport.cursorMode)
1897 sg.add(viewport.getAlignment()
1898 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1900 else if (viewport.getSelectionGroup() != null
1901 && viewport.getSelectionGroup().getSize() != viewport
1902 .getAlignment().getHeight())
1904 sg = viewport.getSelectionGroup()
1905 .getSequences(viewport.getHiddenRepSequences());
1913 List<SequenceI> invertGroup = new ArrayList<>();
1915 for (SequenceI seq : viewport.getAlignment().getSequences())
1917 if (!sg.contains(seq))
1919 invertGroup.add(seq);
1923 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1925 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1926 for (int i = 0; i < invertGroup.size(); i++)
1928 seqs2[i] = invertGroup.get(i);
1931 SlideSequencesCommand ssc;
1934 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1935 viewport.getGapCharacter());
1939 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1940 viewport.getGapCharacter());
1943 int groupAdjustment = 0;
1944 if (ssc.getGapsInsertedBegin() && right)
1946 if (viewport.cursorMode)
1948 alignPanel.getSeqPanel().moveCursor(size, 0);
1952 groupAdjustment = size;
1955 else if (!ssc.getGapsInsertedBegin() && !right)
1957 if (viewport.cursorMode)
1959 alignPanel.getSeqPanel().moveCursor(-size, 0);
1963 groupAdjustment = -size;
1967 if (groupAdjustment != 0)
1969 viewport.getSelectionGroup().setStartRes(
1970 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
1971 viewport.getSelectionGroup().setEndRes(
1972 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
1976 * just extend the last slide command if compatible; but not if in
1977 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
1979 boolean appendHistoryItem = false;
1980 Deque<CommandI> historyList = viewport.getHistoryList();
1981 boolean inSplitFrame = getSplitViewContainer() != null;
1982 if (!inSplitFrame && historyList != null && historyList.size() > 0
1983 && historyList.peek() instanceof SlideSequencesCommand)
1985 appendHistoryItem = ssc.appendSlideCommand(
1986 (SlideSequencesCommand) historyList.peek());
1989 if (!appendHistoryItem)
1991 addHistoryItem(ssc);
2004 protected void copy_actionPerformed()
2006 if (viewport.getSelectionGroup() == null)
2010 // TODO: preserve the ordering of displayed alignment annotation in any
2011 // internal paste (particularly sequence associated annotation)
2012 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2013 String[] omitHidden = null;
2015 if (viewport.hasHiddenColumns())
2017 omitHidden = viewport.getViewAsString(true);
2020 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2021 seqs, omitHidden, null);
2023 StringSelection ss = new StringSelection(output);
2027 jalview.gui.Desktop.internalCopy = true;
2028 // Its really worth setting the clipboard contents
2029 // to empty before setting the large StringSelection!!
2030 Toolkit.getDefaultToolkit().getSystemClipboard()
2031 .setContents(new StringSelection(""), null);
2033 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2035 } catch (OutOfMemoryError er)
2037 new OOMWarning("copying region", er);
2041 HiddenColumns hiddenColumns = null;
2042 if (viewport.hasHiddenColumns())
2044 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2045 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2047 // create new HiddenColumns object with copy of hidden regions
2048 // between startRes and endRes, offset by startRes
2049 hiddenColumns = new HiddenColumns(
2050 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2051 hiddenCutoff, hiddenOffset);
2054 Desktop.jalviewClipboard = new Object[] { seqs,
2055 viewport.getAlignment().getDataset(), hiddenColumns };
2056 setStatus(MessageManager.formatMessage(
2057 "label.copied_sequences_to_clipboard", new Object[]
2058 { Integer.valueOf(seqs.length).toString() }));
2068 protected void pasteNew_actionPerformed(ActionEvent e)
2080 protected void pasteThis_actionPerformed(ActionEvent e)
2086 * Paste contents of Jalview clipboard
2088 * @param newAlignment
2089 * true to paste to a new alignment, otherwise add to this.
2091 void paste(boolean newAlignment)
2093 boolean externalPaste = true;
2096 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2097 Transferable contents = c.getContents(this);
2099 if (contents == null)
2108 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2109 if (str.length() < 1)
2114 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2116 } catch (OutOfMemoryError er)
2118 new OOMWarning("Out of memory pasting sequences!!", er);
2122 SequenceI[] sequences;
2123 boolean annotationAdded = false;
2124 AlignmentI alignment = null;
2126 if (Desktop.jalviewClipboard != null)
2128 // The clipboard was filled from within Jalview, we must use the
2130 // And dataset from the copied alignment
2131 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2132 // be doubly sure that we create *new* sequence objects.
2133 sequences = new SequenceI[newseq.length];
2134 for (int i = 0; i < newseq.length; i++)
2136 sequences[i] = new Sequence(newseq[i]);
2138 alignment = new Alignment(sequences);
2139 externalPaste = false;
2143 // parse the clipboard as an alignment.
2144 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2146 sequences = alignment.getSequencesArray();
2150 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2156 if (Desktop.jalviewClipboard != null)
2158 // dataset is inherited
2159 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2163 // new dataset is constructed
2164 alignment.setDataset(null);
2166 alwidth = alignment.getWidth() + 1;
2170 AlignmentI pastedal = alignment; // preserve pasted alignment object
2171 // Add pasted sequences and dataset into existing alignment.
2172 alignment = viewport.getAlignment();
2173 alwidth = alignment.getWidth() + 1;
2174 // decide if we need to import sequences from an existing dataset
2175 boolean importDs = Desktop.jalviewClipboard != null
2176 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2177 // importDs==true instructs us to copy over new dataset sequences from
2178 // an existing alignment
2179 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2181 // minimum dataset set
2183 for (int i = 0; i < sequences.length; i++)
2187 newDs.addElement(null);
2189 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2191 if (importDs && ds != null)
2193 if (!newDs.contains(ds))
2195 newDs.setElementAt(ds, i);
2196 ds = new Sequence(ds);
2197 // update with new dataset sequence
2198 sequences[i].setDatasetSequence(ds);
2202 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2207 // copy and derive new dataset sequence
2208 sequences[i] = sequences[i].deriveSequence();
2209 alignment.getDataset()
2210 .addSequence(sequences[i].getDatasetSequence());
2211 // TODO: avoid creation of duplicate dataset sequences with a
2212 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2214 alignment.addSequence(sequences[i]); // merges dataset
2218 newDs.clear(); // tidy up
2220 if (alignment.getAlignmentAnnotation() != null)
2222 for (AlignmentAnnotation alan : alignment
2223 .getAlignmentAnnotation())
2225 if (alan.graphGroup > fgroup)
2227 fgroup = alan.graphGroup;
2231 if (pastedal.getAlignmentAnnotation() != null)
2233 // Add any annotation attached to alignment.
2234 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2235 for (int i = 0; i < alann.length; i++)
2237 annotationAdded = true;
2238 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2240 AlignmentAnnotation newann = new AlignmentAnnotation(
2242 if (newann.graphGroup > -1)
2244 if (newGraphGroups.size() <= newann.graphGroup
2245 || newGraphGroups.get(newann.graphGroup) == null)
2247 for (int q = newGraphGroups
2248 .size(); q <= newann.graphGroup; q++)
2250 newGraphGroups.add(q, null);
2252 newGraphGroups.set(newann.graphGroup,
2253 Integer.valueOf(++fgroup));
2255 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2259 newann.padAnnotation(alwidth);
2260 alignment.addAnnotation(newann);
2270 addHistoryItem(new EditCommand(
2271 MessageManager.getString("label.add_sequences"),
2272 Action.PASTE, sequences, 0, alignment.getWidth(),
2275 // Add any annotations attached to sequences
2276 for (int i = 0; i < sequences.length; i++)
2278 if (sequences[i].getAnnotation() != null)
2280 AlignmentAnnotation newann;
2281 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2283 annotationAdded = true;
2284 newann = sequences[i].getAnnotation()[a];
2285 newann.adjustForAlignment();
2286 newann.padAnnotation(alwidth);
2287 if (newann.graphGroup > -1)
2289 if (newann.graphGroup > -1)
2291 if (newGraphGroups.size() <= newann.graphGroup
2292 || newGraphGroups.get(newann.graphGroup) == null)
2294 for (int q = newGraphGroups
2295 .size(); q <= newann.graphGroup; q++)
2297 newGraphGroups.add(q, null);
2299 newGraphGroups.set(newann.graphGroup,
2300 Integer.valueOf(++fgroup));
2302 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2306 alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation
2310 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2318 // propagate alignment changed.
2319 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2320 if (annotationAdded)
2322 // Duplicate sequence annotation in all views.
2323 AlignmentI[] alview = this.getViewAlignments();
2324 for (int i = 0; i < sequences.length; i++)
2326 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2331 for (int avnum = 0; avnum < alview.length; avnum++)
2333 if (alview[avnum] != alignment)
2335 // duplicate in a view other than the one with input focus
2336 int avwidth = alview[avnum].getWidth() + 1;
2337 // this relies on sann being preserved after we
2338 // modify the sequence's annotation array for each duplication
2339 for (int a = 0; a < sann.length; a++)
2341 AlignmentAnnotation newann = new AlignmentAnnotation(
2343 sequences[i].addAlignmentAnnotation(newann);
2344 newann.padAnnotation(avwidth);
2345 alview[avnum].addAnnotation(newann); // annotation was
2346 // duplicated earlier
2347 // TODO JAL-1145 graphGroups are not updated for sequence
2348 // annotation added to several views. This may cause
2350 alview[avnum].setAnnotationIndex(newann, a);
2355 buildSortByAnnotationScoresMenu();
2357 viewport.firePropertyChange("alignment", null,
2358 alignment.getSequences());
2359 if (alignPanels != null)
2361 for (AlignmentPanel ap : alignPanels)
2363 ap.validateAnnotationDimensions(false);
2368 alignPanel.validateAnnotationDimensions(false);
2374 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2376 String newtitle = new String("Copied sequences");
2378 if (Desktop.jalviewClipboard != null
2379 && Desktop.jalviewClipboard[2] != null)
2381 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2382 af.viewport.setHiddenColumns(hc);
2385 // >>>This is a fix for the moment, until a better solution is
2387 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2388 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2389 .getFeatureRenderer());
2391 // TODO: maintain provenance of an alignment, rather than just make the
2392 // title a concatenation of operations.
2395 if (title.startsWith("Copied sequences"))
2401 newtitle = newtitle.concat("- from " + title);
2406 newtitle = new String("Pasted sequences");
2409 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2414 } catch (Exception ex)
2416 ex.printStackTrace();
2417 System.out.println("Exception whilst pasting: " + ex);
2418 // could be anything being pasted in here
2424 protected void expand_newalign(ActionEvent e)
2428 AlignmentI alignment = AlignmentUtils
2429 .expandContext(getViewport().getAlignment(), -1);
2430 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2432 String newtitle = new String("Flanking alignment");
2434 if (Desktop.jalviewClipboard != null
2435 && Desktop.jalviewClipboard[2] != null)
2437 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2438 af.viewport.setHiddenColumns(hc);
2441 // >>>This is a fix for the moment, until a better solution is
2443 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2444 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2445 .getFeatureRenderer());
2447 // TODO: maintain provenance of an alignment, rather than just make the
2448 // title a concatenation of operations.
2450 if (title.startsWith("Copied sequences"))
2456 newtitle = newtitle.concat("- from " + title);
2460 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2462 } catch (Exception ex)
2464 ex.printStackTrace();
2465 System.out.println("Exception whilst pasting: " + ex);
2466 // could be anything being pasted in here
2467 } catch (OutOfMemoryError oom)
2469 new OOMWarning("Viewing flanking region of alignment", oom);
2474 * Action Cut (delete and copy) the selected region
2477 protected void cut_actionPerformed()
2479 copy_actionPerformed();
2480 delete_actionPerformed();
2484 * Performs menu option to Delete the currently selected region
2487 protected void delete_actionPerformed()
2490 SequenceGroup sg = viewport.getSelectionGroup();
2496 Callable okAction = () -> {
2497 SequenceI[] cut = sg.getSequences()
2498 .toArray(new SequenceI[sg.getSize()]);
2500 addHistoryItem(new EditCommand(
2501 MessageManager.getString("label.cut_sequences"), Action.CUT,
2502 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2503 viewport.getAlignment()));
2505 viewport.setSelectionGroup(null);
2506 viewport.sendSelection();
2507 viewport.getAlignment().deleteGroup(sg);
2509 viewport.firePropertyChange("alignment", null,
2510 viewport.getAlignment().getSequences());
2511 if (viewport.getAlignment().getHeight() < 1)
2515 AlignFrame.this.setClosed(true);
2516 } catch (Exception ex)
2524 * If the cut affects all sequences, prompt for confirmation
2526 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2528 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2529 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2530 if (wholeHeight && wholeWidth)
2532 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2533 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2534 Object[] options = new Object[] {
2535 MessageManager.getString("action.ok"),
2536 MessageManager.getString("action.cancel") };
2537 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2538 MessageManager.getString("label.delete_all"),
2539 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2540 options, options[0]);
2547 } catch (Exception e)
2549 e.printStackTrace();
2561 protected void deleteGroups_actionPerformed(ActionEvent e)
2563 if (avc.deleteGroups())
2565 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2566 alignPanel.updateAnnotation();
2567 alignPanel.paintAlignment(true, true);
2578 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2580 SequenceGroup sg = new SequenceGroup(
2581 viewport.getAlignment().getSequences());
2583 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2584 viewport.setSelectionGroup(sg);
2585 viewport.isSelectionGroupChanged(true);
2586 viewport.sendSelection();
2587 // JAL-2034 - should delegate to
2588 // alignPanel to decide if overview needs
2590 alignPanel.paintAlignment(false, false);
2591 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2601 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2603 if (viewport.cursorMode)
2605 alignPanel.getSeqPanel().keyboardNo1 = null;
2606 alignPanel.getSeqPanel().keyboardNo2 = null;
2608 viewport.setSelectionGroup(null);
2609 viewport.getColumnSelection().clear();
2610 viewport.setSearchResults(null);
2611 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2612 // JAL-2034 - should delegate to
2613 // alignPanel to decide if overview needs
2615 alignPanel.paintAlignment(false, false);
2616 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2617 viewport.sendSelection();
2627 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2629 SequenceGroup sg = viewport.getSelectionGroup();
2633 selectAllSequenceMenuItem_actionPerformed(null);
2638 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2640 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2642 // JAL-2034 - should delegate to
2643 // alignPanel to decide if overview needs
2646 alignPanel.paintAlignment(true, false);
2647 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2648 viewport.sendSelection();
2652 public void invertColSel_actionPerformed(ActionEvent e)
2654 viewport.invertColumnSelection();
2655 alignPanel.paintAlignment(true, false);
2656 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2657 viewport.sendSelection();
2667 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2669 trimAlignment(true);
2679 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2681 trimAlignment(false);
2684 void trimAlignment(boolean trimLeft)
2686 ColumnSelection colSel = viewport.getColumnSelection();
2689 if (!colSel.isEmpty())
2693 column = colSel.getMin();
2697 column = colSel.getMax();
2701 if (viewport.getSelectionGroup() != null)
2703 seqs = viewport.getSelectionGroup()
2704 .getSequencesAsArray(viewport.getHiddenRepSequences());
2708 seqs = viewport.getAlignment().getSequencesArray();
2711 TrimRegionCommand trimRegion;
2714 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2715 column, viewport.getAlignment());
2716 viewport.getRanges().setStartRes(0);
2720 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2721 column, viewport.getAlignment());
2724 setStatus(MessageManager.formatMessage("label.removed_columns",
2726 { Integer.valueOf(trimRegion.getSize()).toString() }));
2728 addHistoryItem(trimRegion);
2730 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2732 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2733 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2735 viewport.getAlignment().deleteGroup(sg);
2739 viewport.firePropertyChange("alignment", null,
2740 viewport.getAlignment().getSequences());
2751 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2753 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2756 if (viewport.getSelectionGroup() != null)
2758 seqs = viewport.getSelectionGroup()
2759 .getSequencesAsArray(viewport.getHiddenRepSequences());
2760 start = viewport.getSelectionGroup().getStartRes();
2761 end = viewport.getSelectionGroup().getEndRes();
2765 seqs = viewport.getAlignment().getSequencesArray();
2768 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2769 "Remove Gapped Columns", seqs, start, end,
2770 viewport.getAlignment());
2772 addHistoryItem(removeGapCols);
2774 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2776 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2778 // This is to maintain viewport position on first residue
2779 // of first sequence
2780 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2781 ViewportRanges ranges = viewport.getRanges();
2782 int startRes = seq.findPosition(ranges.getStartRes());
2783 // ShiftList shifts;
2784 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2785 // edit.alColumnChanges=shifts.getInverse();
2786 // if (viewport.hasHiddenColumns)
2787 // viewport.getColumnSelection().compensateForEdits(shifts);
2788 ranges.setStartRes(seq.findIndex(startRes) - 1);
2789 viewport.firePropertyChange("alignment", null,
2790 viewport.getAlignment().getSequences());
2801 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2803 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2806 if (viewport.getSelectionGroup() != null)
2808 seqs = viewport.getSelectionGroup()
2809 .getSequencesAsArray(viewport.getHiddenRepSequences());
2810 start = viewport.getSelectionGroup().getStartRes();
2811 end = viewport.getSelectionGroup().getEndRes();
2815 seqs = viewport.getAlignment().getSequencesArray();
2818 // This is to maintain viewport position on first residue
2819 // of first sequence
2820 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2821 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2823 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2824 viewport.getAlignment()));
2826 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2828 viewport.firePropertyChange("alignment", null,
2829 viewport.getAlignment().getSequences());
2840 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2842 viewport.setPadGaps(padGapsMenuitem.isSelected());
2843 viewport.firePropertyChange("alignment", null,
2844 viewport.getAlignment().getSequences());
2848 * Opens a Finder dialog
2853 public void findMenuItem_actionPerformed(ActionEvent e)
2855 new Finder(alignPanel, false, null);
2859 * Create a new view of the current alignment.
2862 public void newView_actionPerformed(ActionEvent e)
2864 newView(null, true);
2868 * Creates and shows a new view of the current alignment.
2871 * title of newly created view; if null, one will be generated
2872 * @param copyAnnotation
2873 * if true then duplicate all annnotation, groups and settings
2874 * @return new alignment panel, already displayed.
2876 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2879 * Create a new AlignmentPanel (with its own, new Viewport)
2881 AlignmentPanel newap = new jalview.project.Jalview2XML()
2882 .copyAlignPanel(alignPanel);
2883 if (!copyAnnotation)
2886 * remove all groups and annotation except for the automatic stuff
2888 newap.av.getAlignment().deleteAllGroups();
2889 newap.av.getAlignment().deleteAllAnnotations(false);
2892 newap.av.setGatherViewsHere(false);
2894 if (viewport.getViewName() == null)
2896 viewport.setViewName(
2897 MessageManager.getString("label.view_name_original"));
2901 * Views share the same edits undo and redo stacks
2903 newap.av.setHistoryList(viewport.getHistoryList());
2904 newap.av.setRedoList(viewport.getRedoList());
2907 * copy any visualisation settings that are not saved in the project
2909 newap.av.setColourAppliesToAllGroups(
2910 viewport.getColourAppliesToAllGroups());
2913 * Views share the same mappings; need to deregister any new mappings
2914 * created by copyAlignPanel, and register the new reference to the shared
2917 newap.av.replaceMappings(viewport.getAlignment());
2920 * start up cDNA consensus (if applicable) now mappings are in place
2922 if (newap.av.initComplementConsensus())
2924 newap.refresh(true); // adjust layout of annotations
2927 newap.av.setViewName(getNewViewName(viewTitle));
2929 addAlignmentPanel(newap, true);
2930 newap.alignmentChanged();
2932 if (alignPanels.size() == 2)
2934 viewport.setGatherViewsHere(true);
2936 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2942 * Make a new name for the view, ensuring it is unique within the current
2943 * sequenceSetId. (This used to be essential for Jalview Project archives, but
2944 * these now use viewId. Unique view names are still desirable for usability.)
2949 protected String getNewViewName(String viewTitle)
2951 int index = Desktop.getViewCount(viewport.getSequenceSetId());
2952 boolean addFirstIndex = false;
2953 if (viewTitle == null || viewTitle.trim().length() == 0)
2955 viewTitle = MessageManager.getString("action.view");
2956 addFirstIndex = true;
2960 index = 1;// we count from 1 if given a specific name
2962 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
2964 List<Component> comps = PaintRefresher.components
2965 .get(viewport.getSequenceSetId());
2967 List<String> existingNames = getExistingViewNames(comps);
2969 while (existingNames.contains(newViewName))
2971 newViewName = viewTitle + " " + (++index);
2977 * Returns a list of distinct view names found in the given list of
2978 * components. View names are held on the viewport of an AlignmentPanel.
2983 protected List<String> getExistingViewNames(List<Component> comps)
2985 List<String> existingNames = new ArrayList<>();
2986 for (Component comp : comps)
2988 if (comp instanceof AlignmentPanel)
2990 AlignmentPanel ap = (AlignmentPanel) comp;
2991 if (!existingNames.contains(ap.av.getViewName()))
2993 existingNames.add(ap.av.getViewName());
2997 return existingNames;
3001 * Explode tabbed views into separate windows.
3004 public void expandViews_actionPerformed(ActionEvent e)
3006 Desktop.explodeViews(this);
3010 * Gather views in separate windows back into a tabbed presentation.
3013 public void gatherViews_actionPerformed(ActionEvent e)
3015 Desktop.instance.gatherViews(this);
3025 public void font_actionPerformed(ActionEvent e)
3027 new FontChooser(alignPanel);
3037 protected void seqLimit_actionPerformed(ActionEvent e)
3039 viewport.setShowJVSuffix(seqLimits.isSelected());
3041 alignPanel.getIdPanel().getIdCanvas()
3042 .setPreferredSize(alignPanel.calculateIdWidth());
3043 alignPanel.paintAlignment(true, false);
3047 public void idRightAlign_actionPerformed(ActionEvent e)
3049 viewport.setRightAlignIds(idRightAlign.isSelected());
3050 alignPanel.paintAlignment(false, false);
3054 public void centreColumnLabels_actionPerformed(ActionEvent e)
3056 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3057 alignPanel.paintAlignment(false, false);
3063 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3066 protected void followHighlight_actionPerformed()
3069 * Set the 'follow' flag on the Viewport (and scroll to position if now
3072 final boolean state = this.followHighlightMenuItem.getState();
3073 viewport.setFollowHighlight(state);
3076 alignPanel.scrollToPosition(viewport.getSearchResults());
3087 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3089 viewport.setColourText(colourTextMenuItem.isSelected());
3090 alignPanel.paintAlignment(false, false);
3100 public void wrapMenuItem_actionPerformed(ActionEvent e)
3102 scaleAbove.setVisible(wrapMenuItem.isSelected());
3103 scaleLeft.setVisible(wrapMenuItem.isSelected());
3104 scaleRight.setVisible(wrapMenuItem.isSelected());
3105 viewport.setWrapAlignment(wrapMenuItem.isSelected());
3106 alignPanel.updateLayout();
3110 public void showAllSeqs_actionPerformed(ActionEvent e)
3112 viewport.showAllHiddenSeqs();
3116 public void showAllColumns_actionPerformed(ActionEvent e)
3118 viewport.showAllHiddenColumns();
3119 alignPanel.paintAlignment(true, true);
3120 viewport.sendSelection();
3124 public void hideSelSequences_actionPerformed(ActionEvent e)
3126 viewport.hideAllSelectedSeqs();
3130 * called by key handler and the hide all/show all menu items
3135 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3138 boolean hide = false;
3139 SequenceGroup sg = viewport.getSelectionGroup();
3140 if (!toggleSeqs && !toggleCols)
3142 // Hide everything by the current selection - this is a hack - we do the
3143 // invert and then hide
3144 // first check that there will be visible columns after the invert.
3145 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3146 && sg.getStartRes() <= sg.getEndRes()))
3148 // now invert the sequence set, if required - empty selection implies
3149 // that no hiding is required.
3152 invertSequenceMenuItem_actionPerformed(null);
3153 sg = viewport.getSelectionGroup();
3157 viewport.expandColSelection(sg, true);
3158 // finally invert the column selection and get the new sequence
3160 invertColSel_actionPerformed(null);
3167 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3169 hideSelSequences_actionPerformed(null);
3172 else if (!(toggleCols && viewport.hasSelectedColumns()))
3174 showAllSeqs_actionPerformed(null);
3180 if (viewport.hasSelectedColumns())
3182 hideSelColumns_actionPerformed(null);
3185 viewport.setSelectionGroup(sg);
3190 showAllColumns_actionPerformed(null);
3199 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3200 * event.ActionEvent)
3203 public void hideAllButSelection_actionPerformed(ActionEvent e)
3205 toggleHiddenRegions(false, false);
3206 viewport.sendSelection();
3213 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3217 public void hideAllSelection_actionPerformed(ActionEvent e)
3219 SequenceGroup sg = viewport.getSelectionGroup();
3220 viewport.expandColSelection(sg, false);
3221 viewport.hideAllSelectedSeqs();
3222 viewport.hideSelectedColumns();
3223 alignPanel.updateLayout();
3224 alignPanel.paintAlignment(true, true);
3225 viewport.sendSelection();
3232 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3236 public void showAllhidden_actionPerformed(ActionEvent e)
3238 viewport.showAllHiddenColumns();
3239 viewport.showAllHiddenSeqs();
3240 alignPanel.paintAlignment(true, true);
3241 viewport.sendSelection();
3245 public void hideSelColumns_actionPerformed(ActionEvent e)
3247 viewport.hideSelectedColumns();
3248 alignPanel.updateLayout();
3249 alignPanel.paintAlignment(true, true);
3250 viewport.sendSelection();
3254 public void hiddenMarkers_actionPerformed(ActionEvent e)
3256 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3267 protected void scaleAbove_actionPerformed(ActionEvent e)
3269 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3270 alignPanel.updateLayout();
3271 alignPanel.paintAlignment(true, false);
3281 protected void scaleLeft_actionPerformed(ActionEvent e)
3283 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3284 alignPanel.updateLayout();
3285 alignPanel.paintAlignment(true, false);
3295 protected void scaleRight_actionPerformed(ActionEvent e)
3297 viewport.setScaleRightWrapped(scaleRight.isSelected());
3298 alignPanel.updateLayout();
3299 alignPanel.paintAlignment(true, false);
3309 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3311 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3312 alignPanel.paintAlignment(false, false);
3322 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3324 viewport.setShowText(viewTextMenuItem.isSelected());
3325 alignPanel.paintAlignment(false, false);
3335 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3337 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3338 alignPanel.paintAlignment(false, false);
3341 public FeatureSettings featureSettings;
3344 public FeatureSettingsControllerI getFeatureSettingsUI()
3346 return featureSettings;
3350 public void featureSettings_actionPerformed(ActionEvent e)
3352 showFeatureSettingsUI();
3356 public FeatureSettingsControllerI showFeatureSettingsUI()
3358 if (featureSettings != null)
3360 featureSettings.closeOldSettings();
3361 featureSettings = null;
3363 if (!showSeqFeatures.isSelected())
3365 // make sure features are actually displayed
3366 showSeqFeatures.setSelected(true);
3367 showSeqFeatures_actionPerformed(null);
3369 featureSettings = new FeatureSettings(this);
3370 return featureSettings;
3374 * Set or clear 'Show Sequence Features'
3380 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3382 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3383 alignPanel.paintAlignment(true, true);
3387 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3388 * the annotations panel as a whole.
3390 * The options to show/hide all annotations should be enabled when the panel
3391 * is shown, and disabled when the panel is hidden.
3396 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3398 final boolean setVisible = annotationPanelMenuItem.isSelected();
3399 viewport.setShowAnnotation(setVisible);
3400 this.showAllSeqAnnotations.setEnabled(setVisible);
3401 this.hideAllSeqAnnotations.setEnabled(setVisible);
3402 this.showAllAlAnnotations.setEnabled(setVisible);
3403 this.hideAllAlAnnotations.setEnabled(setVisible);
3404 alignPanel.updateLayout();
3408 public void alignmentProperties()
3411 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3414 String content = MessageManager.formatMessage("label.html_content",
3416 { contents.toString() });
3419 if (Platform.isJS())
3421 JLabel textLabel = new JLabel();
3422 textLabel.setText(content);
3423 textLabel.setBackground(Color.WHITE);
3425 pane = new JPanel(new BorderLayout());
3426 ((JPanel) pane).setOpaque(true);
3427 pane.setBackground(Color.WHITE);
3428 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3437 JEditorPane editPane = new JEditorPane("text/html", "");
3438 editPane.setEditable(false);
3439 editPane.setText(content);
3443 JInternalFrame frame = new JInternalFrame();
3445 frame.getContentPane().add(new JScrollPane(pane));
3447 Desktop.addInternalFrame(frame, MessageManager
3448 .formatMessage("label.alignment_properties", new Object[]
3449 { getTitle() }), 500, 400);
3453 * Opens an Overview panel for the alignment, unless one is open already
3458 public void overviewMenuItem_actionPerformed(ActionEvent e)
3460 boolean showHiddenRegions = Cache
3461 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3462 openOverviewPanel(showHiddenRegions);
3465 public OverviewPanel openOverviewPanel(boolean showHidden)
3467 if (alignPanel.overviewPanel != null)
3469 return alignPanel.overviewPanel;
3471 JInternalFrame frame = new JInternalFrame();
3472 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3474 frame.setContentPane(overview);
3475 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3476 frame.getHeight(), true, true);
3477 frame.setFrameIcon(null);
3479 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3480 final AlignmentPanel thePanel = this.alignPanel;
3481 frame.addInternalFrameListener(
3482 new javax.swing.event.InternalFrameAdapter()
3485 public void internalFrameClosed(
3486 javax.swing.event.InternalFrameEvent evt)
3489 thePanel.setOverviewPanel(null);
3492 if (getKeyListeners().length > 0)
3494 frame.addKeyListener(getKeyListeners()[0]);
3497 alignPanel.setOverviewPanel(overview);
3498 alignPanel.setOverviewTitle(this);
3504 public void textColour_actionPerformed()
3506 new TextColourChooser().chooseColour(alignPanel, null);
3510 * public void covariationColour_actionPerformed() {
3512 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3516 public void annotationColour_actionPerformed()
3518 new AnnotationColourChooser(viewport, alignPanel);
3522 public void annotationColumn_actionPerformed(ActionEvent e)
3524 new AnnotationColumnChooser(viewport, alignPanel);
3528 * Action on the user checking or unchecking the option to apply the selected
3529 * colour scheme to all groups. If unchecked, groups may have their own
3530 * independent colour schemes.
3535 public void applyToAllGroups_actionPerformed(boolean selected)
3537 viewport.setColourAppliesToAllGroups(selected);
3541 * Action on user selecting a colour from the colour menu
3544 * the name (not the menu item label!) of the colour scheme
3547 public void changeColour_actionPerformed(String name)
3550 * 'User Defined' opens a panel to configure or load a
3551 * user-defined colour scheme
3553 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3555 new UserDefinedColours(alignPanel);
3560 * otherwise set the chosen colour scheme (or null for 'None')
3562 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3563 viewport, viewport.getAlignment(),
3564 viewport.getHiddenRepSequences());
3569 * Actions on setting or changing the alignment colour scheme
3574 public void changeColour(ColourSchemeI cs)
3576 // TODO: pull up to controller method
3577 ColourMenuHelper.setColourSelected(colourMenu, cs);
3579 viewport.setGlobalColourScheme(cs);
3581 alignPanel.paintAlignment(true, true);
3585 * Show the PID threshold slider panel
3588 protected void modifyPID_actionPerformed()
3590 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3591 alignPanel.getViewName());
3592 SliderPanel.showPIDSlider();
3596 * Show the Conservation slider panel
3599 protected void modifyConservation_actionPerformed()
3601 SliderPanel.setConservationSlider(alignPanel,
3602 viewport.getResidueShading(), alignPanel.getViewName());
3603 SliderPanel.showConservationSlider();
3607 * Action on selecting or deselecting (Colour) By Conservation
3610 public void conservationMenuItem_actionPerformed(boolean selected)
3612 modifyConservation.setEnabled(selected);
3613 viewport.setConservationSelected(selected);
3614 viewport.getResidueShading().setConservationApplied(selected);
3616 changeColour(viewport.getGlobalColourScheme());
3619 modifyConservation_actionPerformed();
3623 SliderPanel.hideConservationSlider();
3628 * Action on selecting or deselecting (Colour) Above PID Threshold
3631 public void abovePIDThreshold_actionPerformed(boolean selected)
3633 modifyPID.setEnabled(selected);
3634 viewport.setAbovePIDThreshold(selected);
3637 viewport.getResidueShading().setThreshold(0,
3638 viewport.isIgnoreGapsConsensus());
3641 changeColour(viewport.getGlobalColourScheme());
3644 modifyPID_actionPerformed();
3648 SliderPanel.hidePIDSlider();
3659 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3661 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3662 AlignmentSorter.sortByPID(viewport.getAlignment(),
3663 viewport.getAlignment().getSequenceAt(0));
3664 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3665 viewport.getAlignment()));
3666 alignPanel.paintAlignment(true, false);
3676 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3678 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3679 AlignmentSorter.sortByID(viewport.getAlignment());
3681 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3682 alignPanel.paintAlignment(true, false);
3692 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3694 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3695 AlignmentSorter.sortByLength(viewport.getAlignment());
3696 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3697 viewport.getAlignment()));
3698 alignPanel.paintAlignment(true, false);
3708 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3710 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3711 AlignmentSorter.sortByGroup(viewport.getAlignment());
3712 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3713 viewport.getAlignment()));
3715 alignPanel.paintAlignment(true, false);
3725 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3727 new RedundancyPanel(alignPanel, this);
3737 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3739 if ((viewport.getSelectionGroup() == null)
3740 || (viewport.getSelectionGroup().getSize() < 2))
3742 JvOptionPane.showInternalMessageDialog(this,
3743 MessageManager.getString(
3744 "label.you_must_select_least_two_sequences"),
3745 MessageManager.getString("label.invalid_selection"),
3746 JvOptionPane.WARNING_MESSAGE);
3750 JInternalFrame frame = new JInternalFrame();
3751 frame.setContentPane(new PairwiseAlignPanel(viewport));
3752 Desktop.addInternalFrame(frame,
3753 MessageManager.getString("action.pairwise_alignment"), 600,
3759 public void autoCalculate_actionPerformed(ActionEvent e)
3761 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3762 if (viewport.autoCalculateConsensus)
3764 viewport.firePropertyChange("alignment", null,
3765 viewport.getAlignment().getSequences());
3770 public void sortByTreeOption_actionPerformed(ActionEvent e)
3772 viewport.sortByTree = sortByTree.isSelected();
3776 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3778 viewport.followSelection = listenToViewSelections.isSelected();
3782 * Constructs a tree panel and adds it to the desktop
3785 * tree type (NJ or AV)
3787 * name of score model used to compute the tree
3789 * parameters for the distance or similarity calculation
3791 void newTreePanel(String type, String modelName,
3792 SimilarityParamsI options)
3794 String frameTitle = "";
3797 boolean onSelection = false;
3798 if (viewport.getSelectionGroup() != null
3799 && viewport.getSelectionGroup().getSize() > 0)
3801 SequenceGroup sg = viewport.getSelectionGroup();
3803 /* Decide if the selection is a column region */
3804 for (SequenceI _s : sg.getSequences())
3806 if (_s.getLength() < sg.getEndRes())
3808 JvOptionPane.showMessageDialog(Desktop.desktop,
3809 MessageManager.getString(
3810 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3811 MessageManager.getString(
3812 "label.sequences_selection_not_aligned"),
3813 JvOptionPane.WARNING_MESSAGE);
3822 if (viewport.getAlignment().getHeight() < 2)
3828 tp = new TreePanel(alignPanel, type, modelName, options);
3829 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3831 frameTitle += " from ";
3833 if (viewport.getViewName() != null)
3835 frameTitle += viewport.getViewName() + " of ";
3838 frameTitle += this.title;
3840 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3851 public void addSortByOrderMenuItem(String title,
3852 final AlignmentOrder order)
3854 final JMenuItem item = new JMenuItem(MessageManager
3855 .formatMessage("action.by_title_param", new Object[]
3858 item.addActionListener(new java.awt.event.ActionListener()
3861 public void actionPerformed(ActionEvent e)
3863 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3865 // TODO: JBPNote - have to map order entries to curent SequenceI
3867 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3869 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3870 viewport.getAlignment()));
3872 alignPanel.paintAlignment(true, false);
3878 * Add a new sort by annotation score menu item
3881 * the menu to add the option to
3883 * the label used to retrieve scores for each sequence on the
3886 public void addSortByAnnotScoreMenuItem(JMenu sort,
3887 final String scoreLabel)
3889 final JMenuItem item = new JMenuItem(scoreLabel);
3891 item.addActionListener(new java.awt.event.ActionListener()
3894 public void actionPerformed(ActionEvent e)
3896 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3897 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3898 viewport.getAlignment());// ,viewport.getSelectionGroup());
3899 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3900 viewport.getAlignment()));
3901 alignPanel.paintAlignment(true, false);
3907 * last hash for alignment's annotation array - used to minimise cost of
3910 protected int _annotationScoreVectorHash;
3913 * search the alignment and rebuild the sort by annotation score submenu the
3914 * last alignment annotation vector hash is stored to minimize cost of
3915 * rebuilding in subsequence calls.
3919 public void buildSortByAnnotationScoresMenu()
3921 if (viewport.getAlignment().getAlignmentAnnotation() == null)
3926 if (viewport.getAlignment().getAlignmentAnnotation()
3927 .hashCode() != _annotationScoreVectorHash)
3929 sortByAnnotScore.removeAll();
3930 // almost certainly a quicker way to do this - but we keep it simple
3931 Hashtable<String, String> scoreSorts = new Hashtable<>();
3932 AlignmentAnnotation aann[];
3933 for (SequenceI sqa : viewport.getAlignment().getSequences())
3935 aann = sqa.getAnnotation();
3936 for (int i = 0; aann != null && i < aann.length; i++)
3938 if (aann[i].hasScore() && aann[i].sequenceRef != null)
3940 scoreSorts.put(aann[i].label, aann[i].label);
3944 Enumeration<String> labels = scoreSorts.keys();
3945 while (labels.hasMoreElements())
3947 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
3949 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
3952 _annotationScoreVectorHash = viewport.getAlignment()
3953 .getAlignmentAnnotation().hashCode();
3958 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
3959 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
3960 * call. Listeners are added to remove the menu item when the treePanel is
3961 * closed, and adjust the tree leaf to sequence mapping when the alignment is
3965 public void buildTreeSortMenu()
3967 sortByTreeMenu.removeAll();
3969 List<Component> comps = PaintRefresher.components
3970 .get(viewport.getSequenceSetId());
3971 List<TreePanel> treePanels = new ArrayList<>();
3972 for (Component comp : comps)
3974 if (comp instanceof TreePanel)
3976 treePanels.add((TreePanel) comp);
3980 if (treePanels.size() < 1)
3982 sortByTreeMenu.setVisible(false);
3986 sortByTreeMenu.setVisible(true);
3988 for (final TreePanel tp : treePanels)
3990 final JMenuItem item = new JMenuItem(tp.getTitle());
3991 item.addActionListener(new java.awt.event.ActionListener()
3994 public void actionPerformed(ActionEvent e)
3996 tp.sortByTree_actionPerformed();
3997 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4002 sortByTreeMenu.add(item);
4006 public boolean sortBy(AlignmentOrder alorder, String undoname)
4008 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4009 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4010 if (undoname != null)
4012 addHistoryItem(new OrderCommand(undoname, oldOrder,
4013 viewport.getAlignment()));
4015 alignPanel.paintAlignment(true, false);
4020 * Work out whether the whole set of sequences or just the selected set will
4021 * be submitted for multiple alignment.
4024 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4026 // Now, check we have enough sequences
4027 AlignmentView msa = null;
4029 if ((viewport.getSelectionGroup() != null)
4030 && (viewport.getSelectionGroup().getSize() > 1))
4032 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4033 // some common interface!
4035 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4036 * SequenceI[sz = seqs.getSize(false)];
4038 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4039 * seqs.getSequenceAt(i); }
4041 msa = viewport.getAlignmentView(true);
4043 else if (viewport.getSelectionGroup() != null
4044 && viewport.getSelectionGroup().getSize() == 1)
4046 int option = JvOptionPane.showConfirmDialog(this,
4047 MessageManager.getString("warn.oneseq_msainput_selection"),
4048 MessageManager.getString("label.invalid_selection"),
4049 JvOptionPane.OK_CANCEL_OPTION);
4050 if (option == JvOptionPane.OK_OPTION)
4052 msa = viewport.getAlignmentView(false);
4057 msa = viewport.getAlignmentView(false);
4063 * Decides what is submitted to a secondary structure prediction service: the
4064 * first sequence in the alignment, or in the current selection, or, if the
4065 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4066 * region or the whole alignment. (where the first sequence in the set is the
4067 * one that the prediction will be for).
4069 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4071 AlignmentView seqs = null;
4073 if ((viewport.getSelectionGroup() != null)
4074 && (viewport.getSelectionGroup().getSize() > 0))
4076 seqs = viewport.getAlignmentView(true);
4080 seqs = viewport.getAlignmentView(false);
4082 // limit sequences - JBPNote in future - could spawn multiple prediction
4084 // TODO: viewport.getAlignment().isAligned is a global state - the local
4085 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4086 if (!viewport.getAlignment().isAligned(false))
4088 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4089 // TODO: if seqs.getSequences().length>1 then should really have warned
4103 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4105 // Pick the tree file
4106 JalviewFileChooser chooser = new JalviewFileChooser(
4107 Cache.getProperty("LAST_DIRECTORY"));
4108 chooser.setFileView(new JalviewFileView());
4109 chooser.setDialogTitle(
4110 MessageManager.getString("label.select_newick_like_tree_file"));
4111 chooser.setToolTipText(
4112 MessageManager.getString("label.load_tree_file"));
4114 chooser.setResponseHandler(0, () -> {
4115 String filePath = chooser.getSelectedFile().getPath();
4116 Cache.setProperty("LAST_DIRECTORY", filePath);
4117 NewickFile fin = null;
4120 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4121 DataSourceType.FILE));
4122 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4123 } catch (Exception ex)
4125 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4126 MessageManager.getString("label.problem_reading_tree_file"),
4127 JvOptionPane.WARNING_MESSAGE);
4128 ex.printStackTrace();
4130 if (fin != null && fin.hasWarningMessage())
4132 JvOptionPane.showMessageDialog(Desktop.desktop,
4133 fin.getWarningMessage(),
4135 .getString("label.possible_problem_with_tree_file"),
4136 JvOptionPane.WARNING_MESSAGE);
4140 chooser.showOpenDialog(this);
4143 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4145 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4148 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4149 int h, int x, int y)
4151 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4155 * Add a treeviewer for the tree extracted from a Newick file object to the
4156 * current alignment view
4163 * Associated alignment input data (or null)
4172 * @return TreePanel handle
4174 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4175 AlignmentView input, int w, int h, int x, int y)
4177 TreePanel tp = null;
4183 if (nf.getTree() != null)
4185 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4191 tp.setLocation(x, y);
4194 Desktop.addInternalFrame(tp, treeTitle, w, h);
4196 } catch (Exception ex)
4198 ex.printStackTrace();
4204 public void showContactMapTree(AlignmentAnnotation aa,
4205 PAEContactMatrix cm)
4208 int w = 400, h = 500;
4212 NewickFile fin = new NewickFile(
4213 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4214 String title = "PAE Matrix Tree for "
4215 + cm.getReferenceSeq().getDisplayId(false);
4217 showColumnWiseTree(fin, aa, title, w, h, x, y);
4218 } catch (Throwable xx)
4220 Console.error("Unexpected exception showing tree for contact matrix",
4225 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4226 String treeTitle, int w, int h, int x, int y)
4231 if (nf.getTree() == null)
4235 TreePanel tp = new TreePanel(alignPanel, nf, aa, title);
4241 tp.setLocation(x, y);
4244 Desktop.addInternalFrame(tp, title, w, h);
4246 } catch (Throwable xx)
4248 Console.error("Unexpected exception showing tree for contact matrix",
4254 private boolean buildingMenu = false;
4257 * Generates menu items and listener event actions for web service clients
4260 public void BuildWebServiceMenu()
4262 while (buildingMenu)
4266 System.err.println("Waiting for building menu to finish.");
4268 } catch (Exception e)
4272 final AlignFrame me = this;
4273 buildingMenu = true;
4274 new Thread(new Runnable()
4279 final List<JMenuItem> legacyItems = new ArrayList<>();
4282 // System.err.println("Building ws menu again "
4283 // + Thread.currentThread());
4284 // TODO: add support for context dependent disabling of services based
4286 // alignment and current selection
4287 // TODO: add additional serviceHandle parameter to specify abstract
4289 // class independently of AbstractName
4290 // TODO: add in rediscovery GUI function to restart discoverer
4291 // TODO: group services by location as well as function and/or
4293 // object broker mechanism.
4294 final Vector<JMenu> wsmenu = new Vector<>();
4295 final IProgressIndicator af = me;
4298 * do not i18n these strings - they are hard-coded in class
4299 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4300 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4302 final JMenu msawsmenu = new JMenu("Alignment");
4303 final JMenu secstrmenu = new JMenu(
4304 "Secondary Structure Prediction");
4305 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4306 final JMenu analymenu = new JMenu("Analysis");
4307 final JMenu dismenu = new JMenu("Protein Disorder");
4308 // JAL-940 - only show secondary structure prediction services from
4309 // the legacy server
4310 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4312 Discoverer.services != null && (Discoverer.services.size() > 0))
4314 // TODO: refactor to allow list of AbstractName/Handler bindings to
4316 // stored or retrieved from elsewhere
4317 // No MSAWS used any more:
4318 // Vector msaws = null; // (Vector)
4319 // Discoverer.services.get("MsaWS");
4320 Vector<ServiceHandle> secstrpr = Discoverer.services
4322 if (secstrpr != null)
4324 // Add any secondary structure prediction services
4325 for (int i = 0, j = secstrpr.size(); i < j; i++)
4327 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4328 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4329 .getServiceClient(sh);
4330 int p = secstrmenu.getItemCount();
4331 impl.attachWSMenuEntry(secstrmenu, me);
4332 int q = secstrmenu.getItemCount();
4333 for (int litm = p; litm < q; litm++)
4335 legacyItems.add(secstrmenu.getItem(litm));
4341 // Add all submenus in the order they should appear on the web
4343 wsmenu.add(msawsmenu);
4344 wsmenu.add(secstrmenu);
4345 wsmenu.add(dismenu);
4346 wsmenu.add(analymenu);
4347 // No search services yet
4348 // wsmenu.add(seqsrchmenu);
4350 javax.swing.SwingUtilities.invokeLater(new Runnable()
4357 webService.removeAll();
4358 // first, add discovered services onto the webservices menu
4359 if (wsmenu.size() > 0)
4361 for (int i = 0, j = wsmenu.size(); i < j; i++)
4363 webService.add(wsmenu.get(i));
4368 webService.add(me.webServiceNoServices);
4370 // TODO: move into separate menu builder class.
4372 // logic for 2.11.1.4 is
4373 // always look to see if there is a discover. if there isn't
4374 // we can't show any Jws2 services
4375 // if there are services available, show them - regardless of
4376 // the 'show JWS2 preference'
4377 // if the discoverer is running then say so
4378 // otherwise offer to trigger discovery if 'show JWS2' is not
4380 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4381 if (jws2servs != null)
4383 if (jws2servs.hasServices())
4385 jws2servs.attachWSMenuEntry(webService, me);
4386 for (Jws2Instance sv : jws2servs.getServices())
4388 if (sv.description.toLowerCase(Locale.ROOT)
4391 for (JMenuItem jmi : legacyItems)
4393 jmi.setVisible(false);
4399 if (jws2servs.isRunning())
4401 JMenuItem tm = new JMenuItem(
4402 "Still discovering JABA Services");
4403 tm.setEnabled(false);
4406 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4408 JMenuItem enableJws2 = new JMenuItem(
4409 "Discover Web Services");
4410 enableJws2.setToolTipText(
4411 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4412 enableJws2.setEnabled(true);
4413 enableJws2.addActionListener(new ActionListener()
4417 public void actionPerformed(ActionEvent e)
4419 // start service discoverer, but ignore preference
4420 Desktop.instance.startServiceDiscovery(false,
4424 webService.add(enableJws2);
4428 build_urlServiceMenu(me.webService);
4429 build_fetchdbmenu(webService);
4430 for (JMenu item : wsmenu)
4432 if (item.getItemCount() == 0)
4434 item.setEnabled(false);
4438 item.setEnabled(true);
4441 } catch (Exception e)
4444 "Exception during web service menu building process.",
4449 } catch (Exception e)
4452 buildingMenu = false;
4459 * construct any groupURL type service menu entries.
4463 protected void build_urlServiceMenu(JMenu webService)
4465 // TODO: remove this code when 2.7 is released
4466 // DEBUG - alignmentView
4468 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4469 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4471 * @Override public void actionPerformed(ActionEvent e) {
4472 * jalview.datamodel.AlignmentView
4473 * .testSelectionViews(af.viewport.getAlignment(),
4474 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4476 * }); webService.add(testAlView);
4478 // TODO: refactor to RestClient discoverer and merge menu entries for
4479 // rest-style services with other types of analysis/calculation service
4480 // SHmmr test client - still being implemented.
4481 // DEBUG - alignmentView
4483 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4486 client.attachWSMenuEntry(
4487 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4493 * Searches the alignment sequences for xRefs and builds the Show
4494 * Cross-References menu (formerly called Show Products), with database
4495 * sources for which cross-references are found (protein sources for a
4496 * nucleotide alignment and vice versa)
4498 * @return true if Show Cross-references menu should be enabled
4500 public boolean canShowProducts()
4502 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4503 AlignmentI dataset = viewport.getAlignment().getDataset();
4505 showProducts.removeAll();
4506 final boolean dna = viewport.getAlignment().isNucleotide();
4508 if (seqs == null || seqs.length == 0)
4510 // nothing to see here.
4514 boolean showp = false;
4517 List<String> ptypes = new CrossRef(seqs, dataset)
4518 .findXrefSourcesForSequences(dna);
4520 for (final String source : ptypes)
4523 final AlignFrame af = this;
4524 JMenuItem xtype = new JMenuItem(source);
4525 xtype.addActionListener(new ActionListener()
4528 public void actionPerformed(ActionEvent e)
4530 showProductsFor(af.viewport.getSequenceSelection(), dna,
4534 showProducts.add(xtype);
4536 showProducts.setVisible(showp);
4537 showProducts.setEnabled(showp);
4538 } catch (Exception e)
4541 "canShowProducts threw an exception - please report to help@jalview.org",
4549 * Finds and displays cross-references for the selected sequences (protein
4550 * products for nucleotide sequences, dna coding sequences for peptides).
4553 * the sequences to show cross-references for
4555 * true if from a nucleotide alignment (so showing proteins)
4557 * the database to show cross-references for
4559 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4560 final String source)
4562 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4567 * Construct and display a new frame containing the translation of this
4568 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4571 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4573 AlignmentI al = null;
4576 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4578 al = dna.translateCdna(codeTable);
4579 } catch (Exception ex)
4581 Console.error("Exception during translation. Please report this !",
4583 final String msg = MessageManager.getString(
4584 "label.error_when_translating_sequences_submit_bug_report");
4585 final String errorTitle = MessageManager
4586 .getString("label.implementation_error")
4587 + MessageManager.getString("label.translation_failed");
4588 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4589 JvOptionPane.ERROR_MESSAGE);
4592 if (al == null || al.getHeight() == 0)
4594 final String msg = MessageManager.getString(
4595 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4596 final String errorTitle = MessageManager
4597 .getString("label.translation_failed");
4598 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4599 JvOptionPane.WARNING_MESSAGE);
4603 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4604 af.setFileFormat(this.currentFileFormat);
4605 final String newTitle = MessageManager
4606 .formatMessage("label.translation_of_params", new Object[]
4607 { this.getTitle(), codeTable.getId() });
4608 af.setTitle(newTitle);
4609 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4611 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4612 viewport.openSplitFrame(af, new Alignment(seqs));
4616 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4623 * Set the file format
4627 public void setFileFormat(FileFormatI format)
4629 this.currentFileFormat = format;
4633 * Try to load a features file onto the alignment.
4636 * contents or path to retrieve file or a File object
4638 * access mode of file (see jalview.io.AlignFile)
4639 * @return true if features file was parsed correctly.
4641 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4644 return avc.parseFeaturesFile(file, sourceType,
4645 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4650 public void refreshFeatureUI(boolean enableIfNecessary)
4652 // note - currently this is only still here rather than in the controller
4653 // because of the featureSettings hard reference that is yet to be
4655 if (enableIfNecessary)
4657 viewport.setShowSequenceFeatures(true);
4658 showSeqFeatures.setSelected(true);
4664 public void dragEnter(DropTargetDragEvent evt)
4669 public void dragExit(DropTargetEvent evt)
4674 public void dragOver(DropTargetDragEvent evt)
4679 public void dropActionChanged(DropTargetDragEvent evt)
4684 public void drop(DropTargetDropEvent evt)
4686 // JAL-1552 - acceptDrop required before getTransferable call for
4687 // Java's Transferable for native dnd
4688 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4689 Transferable t = evt.getTransferable();
4691 final AlignFrame thisaf = this;
4692 final List<Object> files = new ArrayList<>();
4693 List<DataSourceType> protocols = new ArrayList<>();
4697 Desktop.transferFromDropTarget(files, protocols, evt, t);
4698 } catch (Exception e)
4700 e.printStackTrace();
4704 new Thread(new Runnable()
4711 // check to see if any of these files have names matching sequences
4714 SequenceIdMatcher idm = new SequenceIdMatcher(
4715 viewport.getAlignment().getSequencesArray());
4717 * Object[] { String,SequenceI}
4719 ArrayList<Object[]> filesmatched = new ArrayList<>();
4720 ArrayList<Object> filesnotmatched = new ArrayList<>();
4721 for (int i = 0; i < files.size(); i++)
4724 Object file = files.get(i);
4725 String fileName = file.toString();
4727 DataSourceType protocol = (file instanceof File
4728 ? DataSourceType.FILE
4729 : FormatAdapter.checkProtocol(fileName));
4730 if (protocol == DataSourceType.FILE)
4733 if (file instanceof File)
4736 Platform.cacheFileData(fl);
4740 fl = new File(fileName);
4742 pdbfn = fl.getName();
4744 else if (protocol == DataSourceType.URL)
4746 URL url = new URL(fileName);
4747 pdbfn = url.getFile();
4749 if (pdbfn.length() > 0)
4751 // attempt to find a match in the alignment
4752 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4753 int l = 0, c = pdbfn.indexOf(".");
4754 while (mtch == null && c != -1)
4759 } while ((c = pdbfn.indexOf(".", l)) > l);
4762 pdbfn = pdbfn.substring(0, l);
4764 mtch = idm.findAllIdMatches(pdbfn);
4771 type = new IdentifyFile().identify(file, protocol);
4772 } catch (Exception ex)
4776 if (type != null && type.isStructureFile())
4778 filesmatched.add(new Object[] { file, protocol, mtch });
4782 // File wasn't named like one of the sequences or wasn't a PDB
4784 filesnotmatched.add(file);
4788 if (filesmatched.size() > 0)
4790 boolean autoAssociate = Cache
4791 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4794 String msg = MessageManager.formatMessage(
4795 "label.automatically_associate_structure_files_with_sequences_same_name",
4797 { Integer.valueOf(filesmatched.size())
4799 String ttl = MessageManager.getString(
4800 "label.automatically_associate_structure_files_by_name");
4801 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4802 ttl, JvOptionPane.YES_NO_OPTION);
4803 autoAssociate = choice == JvOptionPane.YES_OPTION;
4807 for (Object[] fm : filesmatched)
4809 // try and associate
4810 // TODO: may want to set a standard ID naming formalism for
4811 // associating PDB files which have no IDs.
4812 for (SequenceI toassoc : (SequenceI[]) fm[2])
4814 PDBEntry pe = new AssociatePdbFileWithSeq()
4815 .associatePdbWithSeq(fm[0].toString(),
4816 (DataSourceType) fm[1], toassoc, false,
4820 System.err.println("Associated file : "
4821 + (fm[0].toString()) + " with "
4822 + toassoc.getDisplayId(true));
4826 // TODO: do we need to update overview ? only if features are
4828 alignPanel.paintAlignment(true, false);
4834 * add declined structures as sequences
4836 for (Object[] o : filesmatched)
4838 filesnotmatched.add(o[0]);
4842 if (filesnotmatched.size() > 0)
4844 if (assocfiles > 0 && (Cache.getDefault(
4845 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4846 || JvOptionPane.showConfirmDialog(thisaf,
4847 "<html>" + MessageManager.formatMessage(
4848 "label.ignore_unmatched_dropped_files_info",
4851 filesnotmatched.size())
4854 MessageManager.getString(
4855 "label.ignore_unmatched_dropped_files"),
4856 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4860 for (Object fn : filesnotmatched)
4862 loadJalviewDataFile(fn, null, null, null);
4866 } catch (Exception ex)
4868 ex.printStackTrace();
4876 * Attempt to load a "dropped" file or URL string, by testing in turn for
4878 * <li>an Annotation file</li>
4879 * <li>a JNet file</li>
4880 * <li>a features file</li>
4881 * <li>else try to interpret as an alignment file</li>
4885 * either a filename or a URL string.
4887 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4888 FileFormatI format, SequenceI assocSeq)
4890 // BH 2018 was String file
4893 if (sourceType == null)
4895 sourceType = FormatAdapter.checkProtocol(file);
4897 // if the file isn't identified, or not positively identified as some
4898 // other filetype (PFAM is default unidentified alignment file type) then
4899 // try to parse as annotation.
4900 boolean isAnnotation = (format == null
4901 || FileFormat.Pfam.equals(format))
4902 ? new AnnotationFile().annotateAlignmentView(viewport,
4908 // first see if its a T-COFFEE score file
4909 TCoffeeScoreFile tcf = null;
4912 tcf = new TCoffeeScoreFile(file, sourceType);
4915 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4919 new TCoffeeColourScheme(viewport.getAlignment()));
4920 isAnnotation = true;
4921 setStatus(MessageManager.getString(
4922 "label.successfully_pasted_tcoffee_scores_to_alignment"));
4926 // some problem - if no warning its probable that the ID matching
4927 // process didn't work
4928 JvOptionPane.showMessageDialog(Desktop.desktop,
4929 tcf.getWarningMessage() == null
4930 ? MessageManager.getString(
4931 "label.check_file_matches_sequence_ids_alignment")
4932 : tcf.getWarningMessage(),
4933 MessageManager.getString(
4934 "label.problem_reading_tcoffee_score_file"),
4935 JvOptionPane.WARNING_MESSAGE);
4942 } catch (Exception x)
4945 "Exception when processing data source as T-COFFEE score file",
4951 // try to see if its a JNet 'concise' style annotation file *before*
4953 // try to parse it as a features file
4956 format = new IdentifyFile().identify(file, sourceType);
4958 if (FileFormat.ScoreMatrix == format)
4960 ScoreMatrixFile sm = new ScoreMatrixFile(
4961 new FileParse(file, sourceType));
4963 // todo: i18n this message
4964 setStatus(MessageManager.formatMessage(
4965 "label.successfully_loaded_matrix",
4966 sm.getMatrixName()));
4968 else if (FileFormat.Jnet.equals(format))
4970 JPredFile predictions = new JPredFile(file, sourceType);
4971 new JnetAnnotationMaker();
4972 JnetAnnotationMaker.add_annotation(predictions,
4973 viewport.getAlignment(), 0, false);
4974 viewport.getAlignment().setupJPredAlignment();
4975 isAnnotation = true;
4977 // else if (IdentifyFile.FeaturesFile.equals(format))
4978 else if (FileFormat.Features.equals(format))
4980 if (parseFeaturesFile(file, sourceType))
4982 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
4983 if (splitFrame != null)
4985 splitFrame.repaint();
4989 alignPanel.paintAlignment(true, true);
4995 new FileLoader().LoadFile(viewport, file, sourceType, format);
5002 alignPanel.adjustAnnotationHeight();
5003 viewport.updateSequenceIdColours();
5004 buildSortByAnnotationScoresMenu();
5005 alignPanel.paintAlignment(true, true);
5007 } catch (Exception ex)
5009 ex.printStackTrace();
5010 } catch (OutOfMemoryError oom)
5015 } catch (Exception x)
5020 + (sourceType != null
5021 ? (sourceType == DataSourceType.PASTE
5023 : "using " + sourceType + " from "
5027 ? "(parsing as '" + format + "' file)"
5029 oom, Desktop.desktop);
5034 * Method invoked by the ChangeListener on the tabbed pane, in other words
5035 * when a different tabbed pane is selected by the user or programmatically.
5038 public void tabSelectionChanged(int index)
5043 * update current Overview window title (if there is one)
5044 * to add view name "Original" if necessary
5046 alignPanel.setOverviewTitle(this);
5049 * switch panels and set Overview title (if there is one
5050 * because it was opened automatically)
5052 alignPanel = alignPanels.get(index);
5053 alignPanel.setOverviewTitle(this);
5055 viewport = alignPanel.av;
5056 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5057 setMenusFromViewport(viewport);
5058 if (featureSettings != null && featureSettings.isOpen()
5059 && featureSettings.fr.getViewport() != viewport)
5061 if (viewport.isShowSequenceFeatures())
5063 // refresh the featureSettings to reflect UI change
5064 showFeatureSettingsUI();
5068 // close feature settings for this view.
5069 featureSettings.close();
5076 * 'focus' any colour slider that is open to the selected viewport
5078 if (viewport.getConservationSelected())
5080 SliderPanel.setConservationSlider(alignPanel,
5081 viewport.getResidueShading(), alignPanel.getViewName());
5085 SliderPanel.hideConservationSlider();
5087 if (viewport.getAbovePIDThreshold())
5089 SliderPanel.setPIDSliderSource(alignPanel,
5090 viewport.getResidueShading(), alignPanel.getViewName());
5094 SliderPanel.hidePIDSlider();
5098 * If there is a frame linked to this one in a SplitPane, switch it to the
5099 * same view tab index. No infinite recursion of calls should happen, since
5100 * tabSelectionChanged() should not get invoked on setting the selected
5101 * index to an unchanged value. Guard against setting an invalid index
5102 * before the new view peer tab has been created.
5104 final AlignViewportI peer = viewport.getCodingComplement();
5107 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5108 .getAlignPanel().alignFrame;
5109 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5111 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5117 * On right mouse click on view tab, prompt for and set new view name.
5120 public void tabbedPane_mousePressed(MouseEvent e)
5122 if (e.isPopupTrigger())
5124 String msg = MessageManager.getString("label.enter_view_name");
5125 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5126 String reply = JvOptionPane.showInputDialog(msg, ttl);
5130 viewport.setViewName(reply);
5131 // TODO warn if reply is in getExistingViewNames()?
5132 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5137 public AlignViewport getCurrentView()
5143 * Open the dialog for regex description parsing.
5146 protected void extractScores_actionPerformed(ActionEvent e)
5148 ParseProperties pp = new jalview.analysis.ParseProperties(
5149 viewport.getAlignment());
5150 // TODO: verify regex and introduce GUI dialog for version 2.5
5151 // if (pp.getScoresFromDescription("col", "score column ",
5152 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5154 if (pp.getScoresFromDescription("description column",
5155 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5157 buildSortByAnnotationScoresMenu();
5165 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5169 protected void showDbRefs_actionPerformed(ActionEvent e)
5171 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5177 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5181 protected void showNpFeats_actionPerformed(ActionEvent e)
5183 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5187 * find the viewport amongst the tabs in this alignment frame and close that
5192 public boolean closeView(AlignViewportI av)
5196 this.closeMenuItem_actionPerformed(false);
5199 Component[] comp = tabbedPane.getComponents();
5200 for (int i = 0; comp != null && i < comp.length; i++)
5202 if (comp[i] instanceof AlignmentPanel)
5204 if (((AlignmentPanel) comp[i]).av == av)
5207 closeView((AlignmentPanel) comp[i]);
5215 protected void build_fetchdbmenu(JMenu webService)
5217 // Temporary hack - DBRef Fetcher always top level ws entry.
5218 // TODO We probably want to store a sequence database checklist in
5219 // preferences and have checkboxes.. rather than individual sources selected
5221 final JMenu rfetch = new JMenu(
5222 MessageManager.getString("action.fetch_db_references"));
5223 rfetch.setToolTipText(MessageManager.getString(
5224 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5225 webService.add(rfetch);
5227 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5228 MessageManager.getString("option.trim_retrieved_seqs"));
5229 trimrs.setToolTipText(
5230 MessageManager.getString("label.trim_retrieved_sequences"));
5232 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5233 trimrs.addActionListener(new ActionListener()
5236 public void actionPerformed(ActionEvent e)
5238 trimrs.setSelected(trimrs.isSelected());
5239 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5240 Boolean.valueOf(trimrs.isSelected()).toString());
5244 JMenuItem fetchr = new JMenuItem(
5245 MessageManager.getString("label.standard_databases"));
5246 fetchr.setToolTipText(
5247 MessageManager.getString("label.fetch_embl_uniprot"));
5248 fetchr.addActionListener(new ActionListener()
5252 public void actionPerformed(ActionEvent e)
5254 new Thread(new Runnable()
5259 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5260 .getAlignment().isNucleotide();
5261 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5262 alignPanel.av.getSequenceSelection(),
5263 alignPanel.alignFrame, null,
5264 alignPanel.alignFrame.featureSettings, isNucleotide);
5265 dbRefFetcher.addListener(new FetchFinishedListenerI()
5268 public void finished()
5271 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5272 .getFeatureSettingsModels())
5275 alignPanel.av.mergeFeaturesStyle(srcSettings);
5277 AlignFrame.this.setMenusForViewport();
5280 dbRefFetcher.fetchDBRefs(false);
5288 new Thread(new Runnable()
5293 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5294 .getSequenceFetcherSingleton();
5295 javax.swing.SwingUtilities.invokeLater(new Runnable()
5300 String[] dbclasses = sf.getNonAlignmentSources();
5301 List<DbSourceProxy> otherdb;
5302 JMenu dfetch = new JMenu();
5303 JMenu ifetch = new JMenu();
5304 JMenuItem fetchr = null;
5305 int comp = 0, icomp = 0, mcomp = 15;
5306 String mname = null;
5308 for (String dbclass : dbclasses)
5310 otherdb = sf.getSourceProxy(dbclass);
5311 // add a single entry for this class, or submenu allowing 'fetch
5313 if (otherdb == null || otherdb.size() < 1)
5319 mname = "From " + dbclass;
5321 if (otherdb.size() == 1)
5323 final DbSourceProxy[] dassource = otherdb
5324 .toArray(new DbSourceProxy[0]);
5325 DbSourceProxy src = otherdb.get(0);
5326 fetchr = new JMenuItem(src.getDbSource());
5327 fetchr.addActionListener(new ActionListener()
5331 public void actionPerformed(ActionEvent e)
5333 new Thread(new Runnable()
5339 boolean isNucleotide = alignPanel.alignFrame
5340 .getViewport().getAlignment()
5342 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5343 alignPanel.av.getSequenceSelection(),
5344 alignPanel.alignFrame, dassource,
5345 alignPanel.alignFrame.featureSettings,
5348 .addListener(new FetchFinishedListenerI()
5351 public void finished()
5353 FeatureSettingsModelI srcSettings = dassource[0]
5354 .getFeatureColourScheme();
5355 alignPanel.av.mergeFeaturesStyle(
5357 AlignFrame.this.setMenusForViewport();
5360 dbRefFetcher.fetchDBRefs(false);
5366 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5367 MessageManager.formatMessage(
5368 "label.fetch_retrieve_from", new Object[]
5369 { src.getDbName() })));
5375 final DbSourceProxy[] dassource = otherdb
5376 .toArray(new DbSourceProxy[0]);
5378 DbSourceProxy src = otherdb.get(0);
5379 fetchr = new JMenuItem(MessageManager
5380 .formatMessage("label.fetch_all_param", new Object[]
5381 { src.getDbSource() }));
5382 fetchr.addActionListener(new ActionListener()
5385 public void actionPerformed(ActionEvent e)
5387 new Thread(new Runnable()
5393 boolean isNucleotide = alignPanel.alignFrame
5394 .getViewport().getAlignment()
5396 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5397 alignPanel.av.getSequenceSelection(),
5398 alignPanel.alignFrame, dassource,
5399 alignPanel.alignFrame.featureSettings,
5402 .addListener(new FetchFinishedListenerI()
5405 public void finished()
5407 AlignFrame.this.setMenusForViewport();
5410 dbRefFetcher.fetchDBRefs(false);
5416 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5417 MessageManager.formatMessage(
5418 "label.fetch_retrieve_from_all_sources",
5420 { Integer.valueOf(otherdb.size())
5422 src.getDbSource(), src.getDbName() })));
5425 // and then build the rest of the individual menus
5426 ifetch = new JMenu(MessageManager.formatMessage(
5427 "label.source_from_db_source", new Object[]
5428 { src.getDbSource() }));
5430 String imname = null;
5432 for (DbSourceProxy sproxy : otherdb)
5434 String dbname = sproxy.getDbName();
5435 String sname = dbname.length() > 5
5436 ? dbname.substring(0, 5) + "..."
5438 String msname = dbname.length() > 10
5439 ? dbname.substring(0, 10) + "..."
5443 imname = MessageManager
5444 .formatMessage("label.from_msname", new Object[]
5447 fetchr = new JMenuItem(msname);
5448 final DbSourceProxy[] dassrc = { sproxy };
5449 fetchr.addActionListener(new ActionListener()
5453 public void actionPerformed(ActionEvent e)
5455 new Thread(new Runnable()
5461 boolean isNucleotide = alignPanel.alignFrame
5462 .getViewport().getAlignment()
5464 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5465 alignPanel.av.getSequenceSelection(),
5466 alignPanel.alignFrame, dassrc,
5467 alignPanel.alignFrame.featureSettings,
5470 .addListener(new FetchFinishedListenerI()
5473 public void finished()
5475 AlignFrame.this.setMenusForViewport();
5478 dbRefFetcher.fetchDBRefs(false);
5484 fetchr.setToolTipText(
5485 "<html>" + MessageManager.formatMessage(
5486 "label.fetch_retrieve_from", new Object[]
5490 if (++icomp >= mcomp || i == (otherdb.size()))
5492 ifetch.setText(MessageManager.formatMessage(
5493 "label.source_to_target", imname, sname));
5495 ifetch = new JMenu();
5503 if (comp >= mcomp || dbi >= (dbclasses.length))
5505 dfetch.setText(MessageManager.formatMessage(
5506 "label.source_to_target", mname, dbclass));
5508 dfetch = new JMenu();
5521 * Left justify the whole alignment.
5524 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5526 AlignmentI al = viewport.getAlignment();
5528 viewport.firePropertyChange("alignment", null, al);
5532 * Right justify the whole alignment.
5535 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5537 AlignmentI al = viewport.getAlignment();
5539 viewport.firePropertyChange("alignment", null, al);
5543 public void setShowSeqFeatures(boolean b)
5545 showSeqFeatures.setSelected(b);
5546 viewport.setShowSequenceFeatures(b);
5553 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5554 * awt.event.ActionEvent)
5557 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5559 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5560 alignPanel.paintAlignment(false, false);
5567 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5571 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5573 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5574 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5582 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5583 * .event.ActionEvent)
5586 protected void showGroupConservation_actionPerformed(ActionEvent e)
5588 viewport.setShowGroupConservation(showGroupConservation.getState());
5589 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5596 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5597 * .event.ActionEvent)
5600 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5602 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5603 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5610 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5611 * .event.ActionEvent)
5614 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5616 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5617 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5621 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5623 showSequenceLogo.setState(true);
5624 viewport.setShowSequenceLogo(true);
5625 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5626 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5630 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5632 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5639 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5640 * .event.ActionEvent)
5643 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5645 if (avc.makeGroupsFromSelection())
5647 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5648 alignPanel.updateAnnotation();
5649 alignPanel.paintAlignment(true,
5650 viewport.needToUpdateStructureViews());
5654 public void clearAlignmentSeqRep()
5656 // TODO refactor alignmentseqrep to controller
5657 if (viewport.getAlignment().hasSeqrep())
5659 viewport.getAlignment().setSeqrep(null);
5660 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5661 alignPanel.updateAnnotation();
5662 alignPanel.paintAlignment(true, true);
5667 protected void createGroup_actionPerformed(ActionEvent e)
5669 if (avc.createGroup())
5671 if (applyAutoAnnotationSettings.isSelected())
5673 alignPanel.updateAnnotation(true, false);
5675 alignPanel.alignmentChanged();
5680 protected void unGroup_actionPerformed(ActionEvent e)
5684 alignPanel.alignmentChanged();
5689 * make the given alignmentPanel the currently selected tab
5691 * @param alignmentPanel
5693 public void setDisplayedView(AlignmentPanel alignmentPanel)
5695 if (!viewport.getSequenceSetId()
5696 .equals(alignmentPanel.av.getSequenceSetId()))
5698 throw new Error(MessageManager.getString(
5699 "error.implementation_error_cannot_show_view_alignment_frame"));
5701 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5702 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5704 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5709 * Action on selection of menu options to Show or Hide annotations.
5712 * @param forSequences
5713 * update sequence-related annotations
5714 * @param forAlignment
5715 * update non-sequence-related annotations
5718 public void setAnnotationsVisibility(boolean visible,
5719 boolean forSequences, boolean forAlignment)
5721 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5722 .getAlignmentAnnotation();
5727 for (AlignmentAnnotation aa : anns)
5730 * don't display non-positional annotations on an alignment
5732 if (aa.annotations == null)
5736 boolean apply = (aa.sequenceRef == null && forAlignment)
5737 || (aa.sequenceRef != null && forSequences);
5740 aa.visible = visible;
5743 alignPanel.validateAnnotationDimensions(true);
5744 alignPanel.alignmentChanged();
5748 * Store selected annotation sort order for the view and repaint.
5751 protected void sortAnnotations_actionPerformed()
5753 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5755 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5756 alignPanel.paintAlignment(false, false);
5761 * @return alignment panels in this alignment frame
5763 public List<? extends AlignmentViewPanel> getAlignPanels()
5765 // alignPanels is never null
5766 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5771 * Open a new alignment window, with the cDNA associated with this (protein)
5772 * alignment, aligned as is the protein.
5774 protected void viewAsCdna_actionPerformed()
5776 // TODO no longer a menu action - refactor as required
5777 final AlignmentI alignment = getViewport().getAlignment();
5778 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5779 if (mappings == null)
5783 List<SequenceI> cdnaSeqs = new ArrayList<>();
5784 for (SequenceI aaSeq : alignment.getSequences())
5786 for (AlignedCodonFrame acf : mappings)
5788 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5792 * There is a cDNA mapping for this protein sequence - add to new
5793 * alignment. It will share the same dataset sequence as other mapped
5794 * cDNA (no new mappings need to be created).
5796 final Sequence newSeq = new Sequence(dnaSeq);
5797 newSeq.setDatasetSequence(dnaSeq);
5798 cdnaSeqs.add(newSeq);
5802 if (cdnaSeqs.size() == 0)
5804 // show a warning dialog no mapped cDNA
5807 AlignmentI cdna = new Alignment(
5808 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5809 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5810 AlignFrame.DEFAULT_HEIGHT);
5811 cdna.alignAs(alignment);
5812 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5814 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5815 AlignFrame.DEFAULT_HEIGHT);
5819 * Set visibility of dna/protein complement view (available when shown in a
5825 protected void showComplement_actionPerformed(boolean show)
5827 SplitContainerI sf = getSplitViewContainer();
5830 sf.setComplementVisible(this, show);
5835 * Generate the reverse (optionally complemented) of the selected sequences,
5836 * and add them to the alignment
5839 protected void showReverse_actionPerformed(boolean complement)
5841 AlignmentI al = null;
5844 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5845 al = dna.reverseCdna(complement);
5846 viewport.addAlignment(al, "");
5847 addHistoryItem(new EditCommand(
5848 MessageManager.getString("label.add_sequences"), Action.PASTE,
5849 al.getSequencesArray(), 0, al.getWidth(),
5850 viewport.getAlignment()));
5851 } catch (Exception ex)
5853 System.err.println(ex.getMessage());
5859 * Try to run a script in the Groovy console, having first ensured that this
5860 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5861 * be targeted at this alignment.
5864 protected void runGroovy_actionPerformed()
5866 Jalview.setCurrentAlignFrame(this);
5867 groovy.ui.Console console = Desktop.getGroovyConsole();
5868 if (console != null)
5872 console.runScript();
5873 } catch (Exception ex)
5875 System.err.println((ex.toString()));
5876 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5877 MessageManager.getString("label.couldnt_run_groovy_script"),
5878 MessageManager.getString("label.groovy_support_failed"),
5879 JvOptionPane.ERROR_MESSAGE);
5884 System.err.println("Can't run Groovy script as console not found");
5889 * Hides columns containing (or not containing) a specified feature, provided
5890 * that would not leave all columns hidden
5892 * @param featureType
5893 * @param columnsContaining
5896 public boolean hideFeatureColumns(String featureType,
5897 boolean columnsContaining)
5899 boolean notForHiding = avc.markColumnsContainingFeatures(
5900 columnsContaining, false, false, featureType);
5903 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5904 false, featureType))
5906 getViewport().hideSelectedColumns();
5914 protected void selectHighlightedColumns_actionPerformed(
5915 ActionEvent actionEvent)
5917 // include key modifier check in case user selects from menu
5918 avc.markHighlightedColumns(
5919 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
5920 (actionEvent.getModifiers() & (ActionEvent.META_MASK
5921 | ActionEvent.CTRL_MASK)) != 0);
5925 protected void copyHighlightedColumns_actionPerformed(
5926 ActionEvent actionEvent)
5928 avc.copyHighlightedRegionsToClipboard();
5932 * Rebuilds the Colour menu, including any user-defined colours which have
5933 * been loaded either on startup or during the session
5935 public void buildColourMenu()
5937 colourMenu.removeAll();
5939 colourMenu.add(applyToAllGroups);
5940 colourMenu.add(textColour);
5941 colourMenu.addSeparator();
5943 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
5944 viewport.getAlignment(), false);
5946 colourMenu.add(annotationColour);
5947 bg.add(annotationColour);
5948 colourMenu.addSeparator();
5949 colourMenu.add(conservationMenuItem);
5950 colourMenu.add(modifyConservation);
5951 colourMenu.add(abovePIDThreshold);
5952 colourMenu.add(modifyPID);
5954 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
5955 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
5959 * Open a dialog (if not already open) that allows the user to select and
5960 * calculate PCA or Tree analysis
5962 protected void openTreePcaDialog()
5964 if (alignPanel.getCalculationDialog() == null)
5966 new CalculationChooser(AlignFrame.this);
5971 protected void loadVcf_actionPerformed()
5973 JalviewFileChooser chooser = new JalviewFileChooser(
5974 Cache.getProperty("LAST_DIRECTORY"));
5975 chooser.setFileView(new JalviewFileView());
5976 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
5977 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
5978 final AlignFrame us = this;
5979 chooser.setResponseHandler(0, () -> {
5980 String choice = chooser.getSelectedFile().getPath();
5981 Cache.setProperty("LAST_DIRECTORY", choice);
5982 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
5983 new VCFLoader(choice).loadVCF(seqs, us);
5986 chooser.showOpenDialog(null);
5990 private Rectangle lastFeatureSettingsBounds = null;
5993 public void setFeatureSettingsGeometry(Rectangle bounds)
5995 lastFeatureSettingsBounds = bounds;
5999 public Rectangle getFeatureSettingsGeometry()
6001 return lastFeatureSettingsBounds;
6006 class PrintThread extends Thread
6010 public PrintThread(AlignmentPanel ap)
6015 static PageFormat pf;
6020 PrinterJob printJob = PrinterJob.getPrinterJob();
6024 printJob.setPrintable(ap, pf);
6028 printJob.setPrintable(ap);
6031 if (printJob.printDialog())
6036 } catch (Exception PrintException)
6038 PrintException.printStackTrace();