2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Rectangle;
27 import java.awt.Toolkit;
28 import java.awt.datatransfer.Clipboard;
29 import java.awt.datatransfer.DataFlavor;
30 import java.awt.datatransfer.StringSelection;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.dnd.DnDConstants;
33 import java.awt.dnd.DropTargetDragEvent;
34 import java.awt.dnd.DropTargetDropEvent;
35 import java.awt.dnd.DropTargetEvent;
36 import java.awt.dnd.DropTargetListener;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.awt.print.PageFormat;
47 import java.awt.print.PrinterJob;
48 import java.beans.PropertyChangeEvent;
50 import java.io.FileWriter;
51 import java.io.IOException;
52 import java.io.OutputStreamWriter;
53 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Deque;
58 import java.util.Enumeration;
59 import java.util.Hashtable;
60 import java.util.List;
61 import java.util.Locale;
62 import java.util.Vector;
64 import javax.swing.ButtonGroup;
65 import javax.swing.JCheckBoxMenuItem;
66 import javax.swing.JComponent;
67 import javax.swing.JEditorPane;
68 import javax.swing.JInternalFrame;
69 import javax.swing.JLabel;
70 import javax.swing.JLayeredPane;
71 import javax.swing.JMenu;
72 import javax.swing.JMenuItem;
73 import javax.swing.JPanel;
74 import javax.swing.JScrollPane;
75 import javax.swing.SwingUtilities;
77 import ext.vamsas.ServiceHandle;
78 import jalview.analysis.AlignmentSorter;
79 import jalview.analysis.AlignmentUtils;
80 import jalview.analysis.CrossRef;
81 import jalview.analysis.Dna;
82 import jalview.analysis.GeneticCodeI;
83 import jalview.analysis.ParseProperties;
84 import jalview.analysis.SequenceIdMatcher;
85 import jalview.api.AlignExportSettingsI;
86 import jalview.api.AlignViewControllerGuiI;
87 import jalview.api.AlignViewControllerI;
88 import jalview.api.AlignViewportI;
89 import jalview.api.AlignmentViewPanel;
90 import jalview.api.FeatureSettingsControllerI;
91 import jalview.api.FeatureSettingsModelI;
92 import jalview.api.SplitContainerI;
93 import jalview.api.ViewStyleI;
94 import jalview.api.analysis.SimilarityParamsI;
95 import jalview.bin.Cache;
96 import jalview.bin.Console;
97 import jalview.bin.Jalview;
98 import jalview.commands.CommandI;
99 import jalview.commands.EditCommand;
100 import jalview.commands.EditCommand.Action;
101 import jalview.commands.OrderCommand;
102 import jalview.commands.RemoveGapColCommand;
103 import jalview.commands.RemoveGapsCommand;
104 import jalview.commands.SlideSequencesCommand;
105 import jalview.commands.TrimRegionCommand;
106 import jalview.datamodel.AlignExportSettingsAdapter;
107 import jalview.datamodel.AlignedCodonFrame;
108 import jalview.datamodel.Alignment;
109 import jalview.datamodel.AlignmentAnnotation;
110 import jalview.datamodel.AlignmentExportData;
111 import jalview.datamodel.AlignmentI;
112 import jalview.datamodel.AlignmentOrder;
113 import jalview.datamodel.AlignmentView;
114 import jalview.datamodel.ColumnSelection;
115 import jalview.datamodel.ContactMatrixI;
116 import jalview.datamodel.HiddenColumns;
117 import jalview.datamodel.PDBEntry;
118 import jalview.datamodel.SeqCigar;
119 import jalview.datamodel.Sequence;
120 import jalview.datamodel.SequenceGroup;
121 import jalview.datamodel.SequenceI;
122 import jalview.gui.ColourMenuHelper.ColourChangeListener;
123 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
124 import jalview.io.AlignmentProperties;
125 import jalview.io.AnnotationFile;
126 import jalview.io.BackupFiles;
127 import jalview.io.BioJsHTMLOutput;
128 import jalview.io.DataSourceType;
129 import jalview.io.FileFormat;
130 import jalview.io.FileFormatI;
131 import jalview.io.FileFormats;
132 import jalview.io.FileLoader;
133 import jalview.io.FileParse;
134 import jalview.io.FormatAdapter;
135 import jalview.io.HtmlSvgOutput;
136 import jalview.io.IdentifyFile;
137 import jalview.io.JPredFile;
138 import jalview.io.JalviewFileChooser;
139 import jalview.io.JalviewFileView;
140 import jalview.io.JnetAnnotationMaker;
141 import jalview.io.NewickFile;
142 import jalview.io.ScoreMatrixFile;
143 import jalview.io.TCoffeeScoreFile;
144 import jalview.io.exceptions.ImageOutputException;
145 import jalview.io.vcf.VCFLoader;
146 import jalview.jbgui.GAlignFrame;
147 import jalview.project.Jalview2XML;
148 import jalview.schemes.ColourSchemeI;
149 import jalview.schemes.ColourSchemes;
150 import jalview.schemes.ResidueColourScheme;
151 import jalview.schemes.TCoffeeColourScheme;
152 import jalview.util.HttpUtils;
153 import jalview.util.ImageMaker.TYPE;
154 import jalview.util.MessageManager;
155 import jalview.util.Platform;
156 import jalview.util.imagemaker.BitmapImageSizing;
157 import jalview.viewmodel.AlignmentViewport;
158 import jalview.viewmodel.ViewportRanges;
159 import jalview.ws.DBRefFetcher;
160 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
161 import jalview.ws.jws1.Discoverer;
162 import jalview.ws.jws2.Jws2Discoverer;
163 import jalview.ws.jws2.jabaws2.Jws2Instance;
164 import jalview.ws.seqfetcher.DbSourceProxy;
170 * @version $Revision$
172 @SuppressWarnings("serial")
173 public class AlignFrame extends GAlignFrame implements DropTargetListener,
174 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
177 public static final int DEFAULT_WIDTH = 700;
179 public static final int DEFAULT_HEIGHT = 500;
182 * The currently displayed panel (selected tabbed view if more than one)
184 public AlignmentPanel alignPanel;
186 AlignViewport viewport;
188 public AlignViewControllerI avc;
190 List<AlignmentPanel> alignPanels = new ArrayList<>();
193 * Last format used to load or save alignments in this window
195 FileFormatI currentFileFormat = null;
198 * Current filename for this alignment
200 String fileName = null;
205 * Creates a new AlignFrame object with specific width and height.
211 public AlignFrame(AlignmentI al, int width, int height)
213 this(al, null, width, height);
217 * Creates a new AlignFrame object with specific width, height and
223 * @param sequenceSetId
225 public AlignFrame(AlignmentI al, int width, int height,
226 String sequenceSetId)
228 this(al, null, width, height, sequenceSetId);
232 * Creates a new AlignFrame object with specific width, height and
238 * @param sequenceSetId
241 public AlignFrame(AlignmentI al, int width, int height,
242 String sequenceSetId, String viewId)
244 this(al, null, width, height, sequenceSetId, viewId);
248 * new alignment window with hidden columns
252 * @param hiddenColumns
253 * ColumnSelection or null
255 * Width of alignment frame
259 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
262 this(al, hiddenColumns, width, height, null);
266 * Create alignment frame for al with hiddenColumns, a specific width and
267 * height, and specific sequenceId
270 * @param hiddenColumns
273 * @param sequenceSetId
276 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
277 int height, String sequenceSetId)
279 this(al, hiddenColumns, width, height, sequenceSetId, null);
283 * Create alignment frame for al with hiddenColumns, a specific width and
284 * height, and specific sequenceId
287 * @param hiddenColumns
290 * @param sequenceSetId
295 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
296 int height, String sequenceSetId, String viewId)
298 setSize(width, height);
300 if (al.getDataset() == null)
305 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
307 alignPanel = new AlignmentPanel(this, viewport);
309 addAlignmentPanel(alignPanel, true);
313 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
314 HiddenColumns hiddenColumns, int width, int height)
316 setSize(width, height);
318 if (al.getDataset() == null)
323 viewport = new AlignViewport(al, hiddenColumns);
325 if (hiddenSeqs != null && hiddenSeqs.length > 0)
327 viewport.hideSequence(hiddenSeqs);
329 alignPanel = new AlignmentPanel(this, viewport);
330 addAlignmentPanel(alignPanel, true);
335 * Make a new AlignFrame from existing alignmentPanels
342 public AlignFrame(AlignmentPanel ap)
346 addAlignmentPanel(ap, false);
351 * initalise the alignframe from the underlying viewport data and the
358 // setBackground(Color.white); // BH 2019
360 if (!Jalview.isHeadlessMode())
362 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
365 avc = new jalview.controller.AlignViewController(this, viewport,
367 if (viewport.getAlignmentConservationAnnotation() == null)
369 // BLOSUM62Colour.setEnabled(false);
370 conservationMenuItem.setEnabled(false);
371 modifyConservation.setEnabled(false);
372 // PIDColour.setEnabled(false);
373 // abovePIDThreshold.setEnabled(false);
374 // modifyPID.setEnabled(false);
377 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
379 if (sortby.equals("Id"))
381 sortIDMenuItem_actionPerformed(null);
383 else if (sortby.equals("Pairwise Identity"))
385 sortPairwiseMenuItem_actionPerformed(null);
389 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
391 setMenusFromViewport(viewport);
392 buildSortByAnnotationScoresMenu();
393 calculateTree.addActionListener(new ActionListener()
397 public void actionPerformed(ActionEvent e)
404 if (Desktop.desktop != null)
406 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
407 if (!Platform.isJS())
409 addServiceListeners();
414 if (viewport.getWrapAlignment())
416 wrapMenuItem_actionPerformed(null);
419 if (Cache.getDefault("SHOW_OVERVIEW", false))
421 this.overviewMenuItem_actionPerformed(null);
426 final List<AlignmentViewPanel> selviews = new ArrayList<>();
427 final List<AlignmentPanel> origview = new ArrayList<>();
428 final String menuLabel = MessageManager
429 .getString("label.copy_format_from");
430 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
431 new ViewSetProvider()
435 public AlignmentPanel[] getAllAlignmentPanels()
438 origview.add(alignPanel);
439 // make an array of all alignment panels except for this one
440 List<AlignmentPanel> aps = new ArrayList<>(
441 Arrays.asList(Desktop.getAlignmentPanels(null)));
442 aps.remove(AlignFrame.this.alignPanel);
443 return aps.toArray(new AlignmentPanel[aps.size()]);
445 }, selviews, new ItemListener()
449 public void itemStateChanged(ItemEvent e)
451 if (origview.size() > 0)
453 final AlignmentPanel ap = origview.get(0);
456 * Copy the ViewStyle of the selected panel to 'this one'.
457 * Don't change value of 'scaleProteinAsCdna' unless copying
460 ViewStyleI vs = selviews.get(0).getAlignViewport()
462 boolean fromSplitFrame = selviews.get(0)
463 .getAlignViewport().getCodingComplement() != null;
466 vs.setScaleProteinAsCdna(ap.getAlignViewport()
467 .getViewStyle().isScaleProteinAsCdna());
469 ap.getAlignViewport().setViewStyle(vs);
472 * Also rescale ViewStyle of SplitFrame complement if there is
473 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
474 * the whole ViewStyle (allow cDNA protein to have different
477 AlignViewportI complement = ap.getAlignViewport()
478 .getCodingComplement();
479 if (complement != null && vs.isScaleProteinAsCdna())
481 AlignFrame af = Desktop.getAlignFrameFor(complement);
482 ((SplitFrame) af.getSplitViewContainer())
484 af.setMenusForViewport();
488 ap.setSelected(true);
489 ap.alignFrame.setMenusForViewport();
494 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
495 .indexOf("devel") > -1
496 || Cache.getDefault("VERSION", "DEVELOPMENT")
497 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
499 formatMenu.add(vsel);
501 addFocusListener(new FocusAdapter()
504 public void focusGained(FocusEvent e)
506 Jalview.setCurrentAlignFrame(AlignFrame.this);
513 * Change the filename and format for the alignment, and enable the 'reload'
514 * button functionality.
521 public void setFileName(String file, FileFormatI format)
524 setFileFormat(format);
525 reload.setEnabled(true);
529 * JavaScript will have this, maybe others. More dependable than a file name
530 * and maintains a reference to the actual bytes loaded.
534 public void setFileObject(File file)
536 this.fileObject = file;
540 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
543 void addKeyListener()
545 addKeyListener(new KeyAdapter()
548 public void keyPressed(KeyEvent evt)
550 if (viewport.cursorMode
551 && ((evt.getKeyCode() >= KeyEvent.VK_0
552 && evt.getKeyCode() <= KeyEvent.VK_9)
553 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
554 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
555 && Character.isDigit(evt.getKeyChar()))
557 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
560 switch (evt.getKeyCode())
563 case 27: // escape key
564 deselectAllSequenceMenuItem_actionPerformed(null);
568 case KeyEvent.VK_DOWN:
569 if (evt.isAltDown() || !viewport.cursorMode)
571 moveSelectedSequences(false);
573 if (viewport.cursorMode)
575 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
580 if (evt.isAltDown() || !viewport.cursorMode)
582 moveSelectedSequences(true);
584 if (viewport.cursorMode)
586 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
591 case KeyEvent.VK_LEFT:
592 if (evt.isAltDown() || !viewport.cursorMode)
594 slideSequences(false,
595 alignPanel.getSeqPanel().getKeyboardNo1());
599 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
604 case KeyEvent.VK_RIGHT:
605 if (evt.isAltDown() || !viewport.cursorMode)
607 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
611 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
615 case KeyEvent.VK_SPACE:
616 if (viewport.cursorMode)
618 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
619 || evt.isShiftDown() || evt.isAltDown());
623 // case KeyEvent.VK_A:
624 // if (viewport.cursorMode)
626 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
627 // //jalview.bin.Console.outPrintln("A");
631 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
632 * jalview.bin.Console.outPrintln("closing bracket"); } break;
634 case KeyEvent.VK_DELETE:
635 case KeyEvent.VK_BACK_SPACE:
636 if (!viewport.cursorMode)
638 cut_actionPerformed();
642 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
643 || evt.isShiftDown() || evt.isAltDown());
649 if (viewport.cursorMode)
651 alignPanel.getSeqPanel().setCursorRow();
655 if (viewport.cursorMode && !evt.isControlDown())
657 alignPanel.getSeqPanel().setCursorColumn();
661 if (viewport.cursorMode)
663 alignPanel.getSeqPanel().setCursorPosition();
667 case KeyEvent.VK_ENTER:
668 case KeyEvent.VK_COMMA:
669 if (viewport.cursorMode)
671 alignPanel.getSeqPanel().setCursorRowAndColumn();
676 if (viewport.cursorMode)
678 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
682 if (viewport.cursorMode)
684 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
689 viewport.cursorMode = !viewport.cursorMode;
690 setStatus(MessageManager
691 .formatMessage("label.keyboard_editing_mode", new String[]
692 { (viewport.cursorMode ? "on" : "off") }));
693 if (viewport.cursorMode)
695 ViewportRanges ranges = viewport.getRanges();
696 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
698 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
701 alignPanel.getSeqPanel().seqCanvas.repaint();
707 Help.showHelpWindow();
708 } catch (Exception ex)
710 ex.printStackTrace();
715 boolean toggleSeqs = !evt.isControlDown();
716 boolean toggleCols = !evt.isShiftDown();
717 toggleHiddenRegions(toggleSeqs, toggleCols);
722 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
723 boolean modifyExisting = true; // always modify, don't clear
724 // evt.isShiftDown();
725 boolean invertHighlighted = evt.isAltDown();
726 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
730 case KeyEvent.VK_PAGE_UP:
731 viewport.getRanges().pageUp();
733 case KeyEvent.VK_PAGE_DOWN:
734 viewport.getRanges().pageDown();
740 public void keyReleased(KeyEvent evt)
742 switch (evt.getKeyCode())
744 case KeyEvent.VK_LEFT:
745 if (evt.isAltDown() || !viewport.cursorMode)
747 viewport.firePropertyChange("alignment", null,
748 viewport.getAlignment().getSequences());
752 case KeyEvent.VK_RIGHT:
753 if (evt.isAltDown() || !viewport.cursorMode)
755 viewport.firePropertyChange("alignment", null,
756 viewport.getAlignment().getSequences());
764 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
766 ap.alignFrame = this;
767 avc = new jalview.controller.AlignViewController(this, viewport,
772 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
774 int aSize = alignPanels.size();
776 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
778 if (aSize == 1 && ap.av.getViewName() == null)
780 this.getContentPane().add(ap, BorderLayout.CENTER);
786 setInitialTabVisible();
789 expandViews.setEnabled(true);
790 gatherViews.setEnabled(true);
791 tabbedPane.addTab(ap.av.getViewName(), ap);
793 ap.setVisible(false);
798 if (ap.av.isPadGaps())
800 ap.av.getAlignment().padGaps();
802 ap.av.updateConservation(ap);
803 ap.av.updateConsensus(ap);
804 ap.av.updateStrucConsensus(ap);
808 public void setInitialTabVisible()
810 expandViews.setEnabled(true);
811 gatherViews.setEnabled(true);
812 tabbedPane.setVisible(true);
813 AlignmentPanel first = alignPanels.get(0);
814 tabbedPane.addTab(first.av.getViewName(), first);
815 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
818 public AlignViewport getViewport()
823 /* Set up intrinsic listeners for dynamically generated GUI bits. */
824 private void addServiceListeners()
826 final java.beans.PropertyChangeListener thisListener;
827 Desktop.instance.addJalviewPropertyChangeListener("services",
828 thisListener = new java.beans.PropertyChangeListener()
831 public void propertyChange(PropertyChangeEvent evt)
833 // // jalview.bin.Console.outPrintln("Discoverer property
835 // if (evt.getPropertyName().equals("services"))
837 SwingUtilities.invokeLater(new Runnable()
843 jalview.bin.Console.errPrintln(
844 "Rebuild WS Menu for service change");
845 BuildWebServiceMenu();
852 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
855 public void internalFrameClosed(
856 javax.swing.event.InternalFrameEvent evt)
858 // jalview.bin.Console.outPrintln("deregistering discoverer listener");
859 Desktop.instance.removeJalviewPropertyChangeListener("services",
861 closeMenuItem_actionPerformed(true);
864 // Finally, build the menu once to get current service state
865 new Thread(new Runnable()
870 BuildWebServiceMenu();
876 * Configure menu items that vary according to whether the alignment is
877 * nucleotide or protein
879 public void setGUINucleotide()
881 AlignmentI al = getViewport().getAlignment();
882 boolean nucleotide = al.isNucleotide();
884 loadVcf.setVisible(nucleotide);
885 showTranslation.setVisible(nucleotide);
886 showReverse.setVisible(nucleotide);
887 showReverseComplement.setVisible(nucleotide);
888 conservationMenuItem.setEnabled(!nucleotide);
890 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
891 showGroupConservation.setEnabled(!nucleotide);
893 showComplementMenuItem
894 .setText(nucleotide ? MessageManager.getString("label.protein")
895 : MessageManager.getString("label.nucleotide"));
899 * set up menus for the current viewport. This may be called after any
900 * operation that affects the data in the current view (selection changed,
901 * etc) to update the menus to reflect the new state.
904 public void setMenusForViewport()
906 setMenusFromViewport(viewport);
910 * Need to call this method when tabs are selected for multiple views, or when
911 * loading from Jalview2XML.java
916 public void setMenusFromViewport(AlignViewport av)
918 padGapsMenuitem.setSelected(av.isPadGaps());
919 colourTextMenuItem.setSelected(av.isShowColourText());
920 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
921 modifyPID.setEnabled(abovePIDThreshold.isSelected());
922 conservationMenuItem.setSelected(av.getConservationSelected());
923 modifyConservation.setEnabled(conservationMenuItem.isSelected());
924 seqLimits.setSelected(av.getShowJVSuffix());
925 idRightAlign.setSelected(av.isRightAlignIds());
926 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
927 renderGapsMenuItem.setSelected(av.isRenderGaps());
928 wrapMenuItem.setSelected(av.getWrapAlignment());
929 scaleAbove.setVisible(av.getWrapAlignment());
930 scaleLeft.setVisible(av.getWrapAlignment());
931 scaleRight.setVisible(av.getWrapAlignment());
932 annotationPanelMenuItem.setState(av.isShowAnnotation());
934 * Show/hide annotations only enabled if annotation panel is shown
936 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
937 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
938 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
939 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
940 viewBoxesMenuItem.setSelected(av.getShowBoxes());
941 viewTextMenuItem.setSelected(av.getShowText());
942 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
943 showGroupConsensus.setSelected(av.isShowGroupConsensus());
944 showGroupConservation.setSelected(av.isShowGroupConservation());
945 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
946 showSequenceLogo.setSelected(av.isShowSequenceLogo());
947 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
949 ColourMenuHelper.setColourSelected(colourMenu,
950 av.getGlobalColourScheme());
952 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
953 hiddenMarkers.setState(av.getShowHiddenMarkers());
954 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
955 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
956 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
957 autoCalculate.setSelected(av.autoCalculateConsensus);
958 sortByTree.setSelected(av.sortByTree);
959 listenToViewSelections.setSelected(av.followSelection);
961 showProducts.setEnabled(canShowProducts());
962 setGroovyEnabled(Desktop.getGroovyConsole() != null);
968 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
972 public void setGroovyEnabled(boolean b)
974 runGroovy.setEnabled(b);
977 private IProgressIndicator progressBar;
982 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
985 public void setProgressBar(String message, long id)
987 if (!Platform.isHeadless() && progressBar != null)
988 progressBar.setProgressBar(message, id);
992 public void registerHandler(final long id,
993 final IProgressIndicatorHandler handler)
995 if (progressBar != null)
996 progressBar.registerHandler(id, handler);
1001 * @return true if any progress bars are still active
1004 public boolean operationInProgress()
1006 return progressBar == null ? false : progressBar.operationInProgress();
1010 * Sets the text of the status bar. Note that setting a null or empty value
1011 * will cause the status bar to be hidden, with possibly undesirable flicker
1012 * of the screen layout.
1015 public void setStatus(String text)
1017 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1021 * Added so Castor Mapping file can obtain Jalview Version
1023 public String getVersion()
1025 return Cache.getProperty("VERSION");
1028 public FeatureRenderer getFeatureRenderer()
1030 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1034 public void fetchSequence_actionPerformed()
1036 new SequenceFetcher(this);
1040 public void addFromFile_actionPerformed(ActionEvent e)
1042 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1046 public void reload_actionPerformed(ActionEvent e)
1048 if (fileName != null)
1050 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1051 // originating file's format
1052 // TODO: work out how to recover feature settings for correct view(s) when
1053 // file is reloaded.
1054 if (FileFormat.Jalview.equals(currentFileFormat))
1056 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1057 for (int i = 0; i < frames.length; i++)
1059 if (frames[i] instanceof AlignFrame && frames[i] != this
1060 && ((AlignFrame) frames[i]).fileName != null
1061 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1065 frames[i].setSelected(true);
1066 Desktop.instance.closeAssociatedWindows();
1067 } catch (java.beans.PropertyVetoException ex)
1073 Desktop.instance.closeAssociatedWindows();
1075 FileLoader loader = new FileLoader();
1076 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1077 ? DataSourceType.URL
1078 : DataSourceType.FILE;
1079 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1083 Rectangle bounds = this.getBounds();
1085 FileLoader loader = new FileLoader();
1087 AlignFrame newframe = null;
1089 if (fileObject == null)
1092 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1093 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1094 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1099 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1100 DataSourceType.FILE, currentFileFormat);
1103 newframe.setBounds(bounds);
1104 if (featureSettings != null && featureSettings.isShowing())
1106 final Rectangle fspos = featureSettings.frame.getBounds();
1107 // TODO: need a 'show feature settings' function that takes bounds -
1108 // need to refactor Desktop.addFrame
1109 newframe.featureSettings_actionPerformed(null);
1110 final FeatureSettings nfs = newframe.featureSettings;
1111 SwingUtilities.invokeLater(new Runnable()
1116 nfs.frame.setBounds(fspos);
1119 this.featureSettings.close();
1120 this.featureSettings = null;
1122 this.closeMenuItem_actionPerformed(true);
1128 public void addFromText_actionPerformed(ActionEvent e)
1131 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1135 public void addFromURL_actionPerformed(ActionEvent e)
1137 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1141 public void save_actionPerformed(ActionEvent e)
1143 if (fileName == null || (currentFileFormat == null)
1144 || HttpUtils.startsWithHttpOrHttps(fileName))
1146 saveAs_actionPerformed();
1150 saveAlignment(fileName, currentFileFormat);
1155 * Saves the alignment to a file with a name chosen by the user, if necessary
1156 * warning if a file would be overwritten
1159 public void saveAs_actionPerformed()
1161 String format = currentFileFormat == null ? null
1162 : currentFileFormat.getName();
1163 JalviewFileChooser chooser = JalviewFileChooser
1164 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1166 chooser.setFileView(new JalviewFileView());
1167 chooser.setDialogTitle(
1168 MessageManager.getString("label.save_alignment_to_file"));
1169 chooser.setToolTipText(MessageManager.getString("action.save"));
1171 int value = chooser.showSaveDialog(this);
1173 if (value != JalviewFileChooser.APPROVE_OPTION)
1177 currentFileFormat = chooser.getSelectedFormat();
1178 // todo is this (2005) test now obsolete - value is never null?
1179 while (currentFileFormat == null)
1181 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1183 .getString("label.select_file_format_before_saving"),
1184 MessageManager.getString("label.file_format_not_specified"),
1185 JvOptionPane.WARNING_MESSAGE);
1186 currentFileFormat = chooser.getSelectedFormat();
1187 value = chooser.showSaveDialog(this);
1188 if (value != JalviewFileChooser.APPROVE_OPTION)
1194 fileName = chooser.getSelectedFile().getPath();
1196 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1197 Cache.setProperty("LAST_DIRECTORY", fileName);
1198 saveAlignment(fileName, currentFileFormat);
1201 boolean lastSaveSuccessful = false;
1203 FileFormatI lastFormatSaved;
1205 String lastFilenameSaved;
1208 * Raise a dialog or status message for the last call to saveAlignment.
1210 * @return true if last call to saveAlignment(file, format) was successful.
1212 public boolean isSaveAlignmentSuccessful()
1215 if (!lastSaveSuccessful)
1217 if (!Platform.isHeadless())
1219 JvOptionPane.showInternalMessageDialog(this, MessageManager
1220 .formatMessage("label.couldnt_save_file", new Object[]
1221 { lastFilenameSaved }),
1222 MessageManager.getString("label.error_saving_file"),
1223 JvOptionPane.WARNING_MESSAGE);
1227 Console.error(MessageManager
1228 .formatMessage("label.couldnt_save_file", new Object[]
1229 { lastFilenameSaved }));
1235 setStatus(MessageManager.formatMessage(
1236 "label.successfully_saved_to_file_in_format", new Object[]
1237 { lastFilenameSaved, lastFormatSaved }));
1240 return lastSaveSuccessful;
1244 * Saves the alignment to the specified file path, in the specified format,
1245 * which may be an alignment format, or Jalview project format. If the
1246 * alignment has hidden regions, or the format is one capable of including
1247 * non-sequence data (features, annotations, groups), then the user may be
1248 * prompted to specify what to include in the output.
1253 public void saveAlignment(String file, FileFormatI format)
1255 saveAlignment(file, format, false);
1258 public void saveAlignment(String file, FileFormatI format, boolean stdout)
1260 lastSaveSuccessful = true;
1263 lastFilenameSaved = file;
1265 lastFormatSaved = format;
1267 if (FileFormat.Jalview.equals(format))
1269 String shortName = title;
1270 if (shortName.indexOf(File.separatorChar) > -1)
1272 shortName = shortName
1273 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1275 // TODO deal with stdout=true
1276 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1279 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1280 if (lastSaveSuccessful)
1282 this.getViewport().setSavedUpToDate(true);
1285 statusBar.setText(MessageManager.formatMessage(
1286 "label.successfully_saved_to_file_in_format", new Object[]
1292 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1293 Runnable cancelAction = () -> {
1294 lastSaveSuccessful = false;
1296 Runnable outputAction = () -> {
1297 // todo defer this to inside formatSequences (or later)
1298 AlignmentExportData exportData = viewport.getAlignExportData(options);
1299 String output = new FormatAdapter(alignPanel, options)
1300 .formatSequences(format, exportData.getAlignment(),
1301 exportData.getOmitHidden(),
1302 exportData.getStartEndPostions(),
1303 viewport.getAlignment().getHiddenColumns());
1306 lastSaveSuccessful = false;
1310 // create backupfiles object and get new temp filename destination
1311 boolean doBackup = BackupFiles.getEnabled() && !stdout;
1312 BackupFiles backupfiles = null;
1315 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1316 backupfiles = new BackupFiles(file);
1320 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1322 Console.trace("ALIGNFRAME setting PrintWriter");
1323 PrintWriter out = stdout
1324 ? new PrintWriter(new OutputStreamWriter(System.out))
1325 : new PrintWriter(new FileWriter(tempFilePath));
1327 if (backupfiles != null)
1329 Console.trace("ALIGNFRAME about to write to temp file "
1330 + backupfiles.getTempFilePath());
1337 Console.trace("ALIGNFRAME about to close file");
1339 Console.trace("ALIGNFRAME closed file");
1341 AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
1344 statusBar.setText(MessageManager.formatMessage(
1345 "label.successfully_printed_to_stdout_in_format",
1347 { format.getName() }));
1351 statusBar.setText(MessageManager.formatMessage(
1352 "label.successfully_saved_to_file_in_format",
1354 { fileName, format.getName() }));
1356 lastSaveSuccessful = true;
1357 } catch (IOException e)
1359 lastSaveSuccessful = false;
1361 "ALIGNFRAME Something happened writing the temp file");
1362 Console.error(e.getMessage());
1363 Console.debug(Cache.getStackTraceString(e));
1364 } catch (Exception ex)
1366 lastSaveSuccessful = false;
1368 "ALIGNFRAME Something unexpected happened writing the temp file");
1369 Console.error(ex.getMessage());
1370 Console.debug(Cache.getStackTraceString(ex));
1375 backupfiles.setWriteSuccess(lastSaveSuccessful);
1376 Console.debug("ALIGNFRAME writing temp file was "
1377 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1378 // do the backup file roll and rename the temp file to actual file
1379 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1380 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1381 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1382 + (lastSaveSuccessful ? "" : "un") + "successfully");
1385 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1386 if (lastSaveSuccessful)
1388 AlignFrame.this.getViewport().setSavedUpToDate(true);
1394 * show dialog with export options if applicable; else just do it
1396 if (AlignExportOptions.isNeeded(viewport, format))
1398 AlignExportOptions choices = new AlignExportOptions(
1399 alignPanel.getAlignViewport(), format, options);
1400 choices.setResponseAction(0, outputAction);
1401 choices.setResponseAction(1, cancelAction);
1402 choices.showDialog();
1409 } catch (Exception e)
1411 // TODO Auto-generated catch block
1412 e.printStackTrace();
1418 * Outputs the alignment to textbox in the requested format, if necessary
1419 * first prompting the user for whether to include hidden regions or
1422 * @param fileFormatName
1425 protected void outputText_actionPerformed(String fileFormatName)
1427 FileFormatI fileFormat = FileFormats.getInstance()
1428 .forName(fileFormatName);
1429 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1430 Runnable outputAction = () -> {
1431 // todo defer this to inside formatSequences (or later)
1432 AlignmentExportData exportData = viewport.getAlignExportData(options);
1433 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1434 cap.setForInput(null);
1437 FileFormatI format = fileFormat;
1438 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1439 format, exportData.getAlignment(),
1440 exportData.getOmitHidden(),
1441 exportData.getStartEndPostions(),
1442 viewport.getAlignment().getHiddenColumns()));
1443 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1444 "label.alignment_output_command", new Object[]
1445 { fileFormat.getName() }), 600, 500);
1446 } catch (OutOfMemoryError oom)
1448 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1455 * show dialog with export options if applicable; else just do it
1457 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1459 AlignExportOptions choices = new AlignExportOptions(
1460 alignPanel.getAlignViewport(), fileFormat, options);
1461 choices.setResponseAction(0, outputAction);
1462 choices.showDialog();
1469 } catch (Exception e)
1471 e.printStackTrace();
1483 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1485 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1488 htmlSVG.exportHTML(null);
1489 } catch (ImageOutputException x)
1491 // report problem to console and raise dialog
1496 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1498 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1501 bjs.exportHTML(null);
1502 } catch (ImageOutputException x)
1504 // report problem to console and raise dialog
1508 public void createImageMap(File file, String image)
1512 alignPanel.makePNGImageMap(file, image);
1513 } catch (ImageOutputException x)
1515 // report problem to console and raise dialog
1520 public void createPNG_actionPerformed(ActionEvent e)
1525 } catch (ImageOutputException ioex)
1527 // raise dialog, and report via console
1532 public void createEPS_actionPerformed(ActionEvent e)
1537 } catch (ImageOutputException ioex)
1539 // raise dialog, and report via console
1545 public void createSVG_actionPerformed(ActionEvent e)
1550 } catch (ImageOutputException ioex)
1552 // raise dialog, and report via console
1558 * Creates a PNG image of the alignment and writes it to the given file. If
1559 * the file is null, the user is prompted to choose a file.
1563 public void createPNG(File f) throws ImageOutputException
1565 createPNG(f, null, BitmapImageSizing.defaultBitmapImageSizing());
1568 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1569 throws ImageOutputException
1571 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1575 * Creates an EPS image of the alignment and writes it to the given file. If
1576 * the file is null, the user is prompted to choose a file.
1580 public void createEPS(File f) throws ImageOutputException
1585 public void createEPS(File f, String renderer) throws ImageOutputException
1587 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1591 * Creates an SVG image of the alignment and writes it to the given file. If
1592 * the file is null, the user is prompted to choose a file.
1596 public void createSVG(File f) throws ImageOutputException
1601 public void createSVG(File f, String renderer) throws ImageOutputException
1603 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1607 public void pageSetup_actionPerformed(ActionEvent e)
1609 PrinterJob printJob = PrinterJob.getPrinterJob();
1610 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1620 public void printMenuItem_actionPerformed(ActionEvent e)
1622 // Putting in a thread avoids Swing painting problems
1623 PrintThread thread = new PrintThread(alignPanel);
1628 public void exportFeatures_actionPerformed(ActionEvent e)
1630 new AnnotationExporter(alignPanel).exportFeatures();
1634 public void exportAnnotations_actionPerformed(ActionEvent e)
1636 new AnnotationExporter(alignPanel).exportAnnotations();
1640 public void associatedData_actionPerformed(ActionEvent e)
1642 final JalviewFileChooser chooser = new JalviewFileChooser(
1643 Cache.getProperty("LAST_DIRECTORY"));
1644 chooser.setFileView(new JalviewFileView());
1645 String tooltip = MessageManager
1646 .getString("label.load_jalview_annotations");
1647 chooser.setDialogTitle(tooltip);
1648 chooser.setToolTipText(tooltip);
1649 chooser.setResponseHandler(0, () -> {
1650 String choice = chooser.getSelectedFile().getPath();
1651 Cache.setProperty("LAST_DIRECTORY", choice);
1652 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1655 chooser.showOpenDialog(this);
1659 * Close the current view or all views in the alignment frame. If the frame
1660 * only contains one view then the alignment will be removed from memory.
1662 * @param closeAllTabs
1665 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1667 if (alignPanels != null && alignPanels.size() < 2)
1669 closeAllTabs = true;
1672 Desktop.closeModal(this);
1676 if (alignPanels != null)
1680 if (this.isClosed())
1682 // really close all the windows - otherwise wait till
1683 // setClosed(true) is called
1684 for (int i = 0; i < alignPanels.size(); i++)
1686 AlignmentPanel ap = alignPanels.get(i);
1693 closeView(alignPanel);
1698 if (featureSettings != null && featureSettings.isOpen())
1700 featureSettings.close();
1701 featureSettings = null;
1705 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1706 * be called recursively, with the frame now in 'closed' state
1708 this.setClosed(true);
1710 } catch (Exception ex)
1712 ex.printStackTrace();
1717 * Close the specified panel and close up tabs appropriately.
1719 * @param panelToClose
1721 public void closeView(AlignmentPanel panelToClose)
1723 int index = tabbedPane.getSelectedIndex();
1724 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1725 alignPanels.remove(panelToClose);
1726 panelToClose.closePanel();
1727 panelToClose = null;
1729 tabbedPane.removeTabAt(closedindex);
1730 tabbedPane.validate();
1732 if (index > closedindex || index == tabbedPane.getTabCount())
1734 // modify currently selected tab index if necessary.
1738 this.tabSelectionChanged(index);
1744 void updateEditMenuBar()
1747 if (viewport.getHistoryList().size() > 0)
1749 undoMenuItem.setEnabled(true);
1750 CommandI command = viewport.getHistoryList().peek();
1751 undoMenuItem.setText(MessageManager
1752 .formatMessage("label.undo_command", new Object[]
1753 { command.getDescription() }));
1757 undoMenuItem.setEnabled(false);
1758 undoMenuItem.setText(MessageManager.getString("action.undo"));
1761 if (viewport.getRedoList().size() > 0)
1763 redoMenuItem.setEnabled(true);
1765 CommandI command = viewport.getRedoList().peek();
1766 redoMenuItem.setText(MessageManager
1767 .formatMessage("label.redo_command", new Object[]
1768 { command.getDescription() }));
1772 redoMenuItem.setEnabled(false);
1773 redoMenuItem.setText(MessageManager.getString("action.redo"));
1778 public void addHistoryItem(CommandI command)
1780 if (command.getSize() > 0)
1782 viewport.addToHistoryList(command);
1783 viewport.clearRedoList();
1784 updateEditMenuBar();
1785 viewport.updateHiddenColumns();
1786 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1787 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1788 // viewport.getColumnSelection()
1789 // .getHiddenColumns().size() > 0);
1795 * @return alignment objects for all views
1797 public AlignmentI[] getViewAlignments()
1799 if (alignPanels != null)
1801 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1803 for (AlignmentPanel ap : alignPanels)
1805 als[i++] = ap.av.getAlignment();
1809 if (viewport != null)
1811 return new AlignmentI[] { viewport.getAlignment() };
1823 protected void undoMenuItem_actionPerformed(ActionEvent e)
1825 if (viewport.getHistoryList().isEmpty())
1829 CommandI command = viewport.getHistoryList().pop();
1830 viewport.addToRedoList(command);
1831 command.undoCommand(getViewAlignments());
1833 AlignmentViewport originalSource = getOriginatingSource(command);
1834 updateEditMenuBar();
1836 if (originalSource != null)
1838 if (originalSource != viewport)
1841 "Implementation worry: mismatch of viewport origin for undo");
1843 originalSource.updateHiddenColumns();
1844 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1846 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1847 // viewport.getColumnSelection()
1848 // .getHiddenColumns().size() > 0);
1849 originalSource.firePropertyChange("alignment", null,
1850 originalSource.getAlignment().getSequences());
1861 protected void redoMenuItem_actionPerformed(ActionEvent e)
1863 if (viewport.getRedoList().size() < 1)
1868 CommandI command = viewport.getRedoList().pop();
1869 viewport.addToHistoryList(command);
1870 command.doCommand(getViewAlignments());
1872 AlignmentViewport originalSource = getOriginatingSource(command);
1873 updateEditMenuBar();
1875 if (originalSource != null)
1878 if (originalSource != viewport)
1881 "Implementation worry: mismatch of viewport origin for redo");
1883 originalSource.updateHiddenColumns();
1884 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1886 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1887 // viewport.getColumnSelection()
1888 // .getHiddenColumns().size() > 0);
1889 originalSource.firePropertyChange("alignment", null,
1890 originalSource.getAlignment().getSequences());
1894 AlignmentViewport getOriginatingSource(CommandI command)
1896 AlignmentViewport originalSource = null;
1897 // For sequence removal and addition, we need to fire
1898 // the property change event FROM the viewport where the
1899 // original alignment was altered
1900 AlignmentI al = null;
1901 if (command instanceof EditCommand)
1903 EditCommand editCommand = (EditCommand) command;
1904 al = editCommand.getAlignment();
1905 List<Component> comps = PaintRefresher.components
1906 .get(viewport.getSequenceSetId());
1908 for (Component comp : comps)
1910 if (comp instanceof AlignmentPanel)
1912 if (al == ((AlignmentPanel) comp).av.getAlignment())
1914 originalSource = ((AlignmentPanel) comp).av;
1921 if (originalSource == null)
1923 // The original view is closed, we must validate
1924 // the current view against the closed view first
1927 PaintRefresher.validateSequences(al, viewport.getAlignment());
1930 originalSource = viewport;
1933 return originalSource;
1937 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1938 * or the sequence under cursor in keyboard mode
1943 public void moveSelectedSequences(boolean up)
1945 SequenceGroup sg = viewport.getSelectionGroup();
1949 if (viewport.cursorMode)
1951 sg = new SequenceGroup();
1952 sg.addSequence(viewport.getAlignment().getSequenceAt(
1953 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1961 if (sg.getSize() < 1)
1966 // TODO: JAL-3733 - add an event to the undo buffer for this !
1968 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1969 viewport.getHiddenRepSequences(), up);
1970 alignPanel.paintAlignment(true, false);
1973 synchronized void slideSequences(boolean right, int size)
1975 List<SequenceI> sg = new ArrayList<>();
1976 if (viewport.cursorMode)
1978 sg.add(viewport.getAlignment()
1979 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1981 else if (viewport.getSelectionGroup() != null
1982 && viewport.getSelectionGroup().getSize() != viewport
1983 .getAlignment().getHeight())
1985 sg = viewport.getSelectionGroup()
1986 .getSequences(viewport.getHiddenRepSequences());
1994 List<SequenceI> invertGroup = new ArrayList<>();
1996 for (SequenceI seq : viewport.getAlignment().getSequences())
1998 if (!sg.contains(seq))
2000 invertGroup.add(seq);
2004 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
2006 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2007 for (int i = 0; i < invertGroup.size(); i++)
2009 seqs2[i] = invertGroup.get(i);
2012 SlideSequencesCommand ssc;
2015 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2016 viewport.getGapCharacter());
2020 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2021 viewport.getGapCharacter());
2024 int groupAdjustment = 0;
2025 if (ssc.getGapsInsertedBegin() && right)
2027 if (viewport.cursorMode)
2029 alignPanel.getSeqPanel().moveCursor(size, 0);
2033 groupAdjustment = size;
2036 else if (!ssc.getGapsInsertedBegin() && !right)
2038 if (viewport.cursorMode)
2040 alignPanel.getSeqPanel().moveCursor(-size, 0);
2044 groupAdjustment = -size;
2048 if (groupAdjustment != 0)
2050 viewport.getSelectionGroup().setStartRes(
2051 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2052 viewport.getSelectionGroup().setEndRes(
2053 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2057 * just extend the last slide command if compatible; but not if in
2058 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2060 boolean appendHistoryItem = false;
2061 Deque<CommandI> historyList = viewport.getHistoryList();
2062 boolean inSplitFrame = getSplitViewContainer() != null;
2063 if (!inSplitFrame && historyList != null && historyList.size() > 0
2064 && historyList.peek() instanceof SlideSequencesCommand)
2066 appendHistoryItem = ssc.appendSlideCommand(
2067 (SlideSequencesCommand) historyList.peek());
2070 if (!appendHistoryItem)
2072 addHistoryItem(ssc);
2085 protected void copy_actionPerformed()
2087 if (viewport.getSelectionGroup() == null)
2091 // TODO: preserve the ordering of displayed alignment annotation in any
2092 // internal paste (particularly sequence associated annotation)
2093 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2094 String[] omitHidden = null;
2096 if (viewport.hasHiddenColumns())
2098 omitHidden = viewport.getViewAsString(true);
2101 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2102 seqs, omitHidden, null);
2104 StringSelection ss = new StringSelection(output);
2108 jalview.gui.Desktop.internalCopy = true;
2109 // Its really worth setting the clipboard contents
2110 // to empty before setting the large StringSelection!!
2111 Toolkit.getDefaultToolkit().getSystemClipboard()
2112 .setContents(new StringSelection(""), null);
2114 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2116 } catch (OutOfMemoryError er)
2118 new OOMWarning("copying region", er);
2122 HiddenColumns hiddenColumns = null;
2123 if (viewport.hasHiddenColumns())
2125 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2126 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2128 // create new HiddenColumns object with copy of hidden regions
2129 // between startRes and endRes, offset by startRes
2130 hiddenColumns = new HiddenColumns(
2131 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2132 hiddenCutoff, hiddenOffset);
2135 Desktop.jalviewClipboard = new Object[] { seqs,
2136 viewport.getAlignment().getDataset(), hiddenColumns };
2137 setStatus(MessageManager.formatMessage(
2138 "label.copied_sequences_to_clipboard", new Object[]
2139 { Integer.valueOf(seqs.length).toString() }));
2149 protected void pasteNew_actionPerformed(ActionEvent e)
2161 protected void pasteThis_actionPerformed(ActionEvent e)
2167 * Paste contents of Jalview clipboard
2169 * @param newAlignment
2170 * true to paste to a new alignment, otherwise add to this.
2172 void paste(boolean newAlignment)
2174 boolean externalPaste = true;
2177 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2178 Transferable contents = c.getContents(this);
2180 if (contents == null)
2189 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2190 if (str.length() < 1)
2195 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2197 } catch (OutOfMemoryError er)
2199 new OOMWarning("Out of memory pasting sequences!!", er);
2203 SequenceI[] sequences;
2204 boolean annotationAdded = false;
2205 AlignmentI alignment = null;
2207 if (Desktop.jalviewClipboard != null)
2209 // The clipboard was filled from within Jalview, we must use the
2211 // And dataset from the copied alignment
2212 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2213 // be doubly sure that we create *new* sequence objects.
2214 sequences = new SequenceI[newseq.length];
2215 for (int i = 0; i < newseq.length; i++)
2217 sequences[i] = new Sequence(newseq[i]);
2219 alignment = new Alignment(sequences);
2220 externalPaste = false;
2224 // parse the clipboard as an alignment.
2225 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2227 sequences = alignment.getSequencesArray();
2231 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2237 if (Desktop.jalviewClipboard != null)
2239 // dataset is inherited
2240 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2244 // new dataset is constructed
2245 alignment.setDataset(null);
2247 alwidth = alignment.getWidth() + 1;
2251 AlignmentI pastedal = alignment; // preserve pasted alignment object
2252 // Add pasted sequences and dataset into existing alignment.
2253 alignment = viewport.getAlignment();
2254 alwidth = alignment.getWidth() + 1;
2255 // decide if we need to import sequences from an existing dataset
2256 boolean importDs = Desktop.jalviewClipboard != null
2257 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2258 // importDs==true instructs us to copy over new dataset sequences from
2259 // an existing alignment
2260 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2262 // minimum dataset set
2264 for (int i = 0; i < sequences.length; i++)
2268 newDs.addElement(null);
2270 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2272 if (importDs && ds != null)
2274 if (!newDs.contains(ds))
2276 newDs.setElementAt(ds, i);
2277 ds = new Sequence(ds);
2278 // update with new dataset sequence
2279 sequences[i].setDatasetSequence(ds);
2283 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2288 // copy and derive new dataset sequence
2289 sequences[i] = sequences[i].deriveSequence();
2290 alignment.getDataset()
2291 .addSequence(sequences[i].getDatasetSequence());
2292 // TODO: avoid creation of duplicate dataset sequences with a
2293 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2295 alignment.addSequence(sequences[i]); // merges dataset
2299 newDs.clear(); // tidy up
2301 if (alignment.getAlignmentAnnotation() != null)
2303 for (AlignmentAnnotation alan : alignment
2304 .getAlignmentAnnotation())
2306 if (alan.graphGroup > fgroup)
2308 fgroup = alan.graphGroup;
2312 if (pastedal.getAlignmentAnnotation() != null)
2314 // Add any annotation attached to alignment.
2315 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2316 for (int i = 0; i < alann.length; i++)
2318 annotationAdded = true;
2319 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2321 AlignmentAnnotation newann = new AlignmentAnnotation(
2323 if (newann.graphGroup > -1)
2325 if (newGraphGroups.size() <= newann.graphGroup
2326 || newGraphGroups.get(newann.graphGroup) == null)
2328 for (int q = newGraphGroups
2329 .size(); q <= newann.graphGroup; q++)
2331 newGraphGroups.add(q, null);
2333 newGraphGroups.set(newann.graphGroup,
2334 Integer.valueOf(++fgroup));
2336 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2340 newann.padAnnotation(alwidth);
2341 alignment.addAnnotation(newann);
2351 addHistoryItem(new EditCommand(
2352 MessageManager.getString("label.add_sequences"),
2353 Action.PASTE, sequences, 0, alignment.getWidth(),
2356 // Add any annotations attached to sequences
2357 for (int i = 0; i < sequences.length; i++)
2359 if (sequences[i].getAnnotation() != null)
2361 AlignmentAnnotation newann;
2362 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2364 annotationAdded = true;
2365 newann = sequences[i].getAnnotation()[a];
2366 newann.adjustForAlignment();
2367 newann.padAnnotation(alwidth);
2368 if (newann.graphGroup > -1)
2370 if (newann.graphGroup > -1)
2372 if (newGraphGroups.size() <= newann.graphGroup
2373 || newGraphGroups.get(newann.graphGroup) == null)
2375 for (int q = newGraphGroups
2376 .size(); q <= newann.graphGroup; q++)
2378 newGraphGroups.add(q, null);
2380 newGraphGroups.set(newann.graphGroup,
2381 Integer.valueOf(++fgroup));
2383 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2387 // annotation was duplicated earlier
2388 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2389 // take care of contact matrix too
2390 ContactMatrixI cm = sequences[i]
2391 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2394 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2398 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2406 // propagate alignment changed.
2407 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2408 if (annotationAdded)
2410 // Duplicate sequence annotation in all views.
2411 AlignmentI[] alview = this.getViewAlignments();
2412 for (int i = 0; i < sequences.length; i++)
2414 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2419 for (int avnum = 0; avnum < alview.length; avnum++)
2421 if (alview[avnum] != alignment)
2423 // duplicate in a view other than the one with input focus
2424 int avwidth = alview[avnum].getWidth() + 1;
2425 // this relies on sann being preserved after we
2426 // modify the sequence's annotation array for each duplication
2427 for (int a = 0; a < sann.length; a++)
2429 AlignmentAnnotation newann = new AlignmentAnnotation(
2431 sequences[i].addAlignmentAnnotation(newann);
2432 newann.padAnnotation(avwidth);
2433 alview[avnum].addAnnotation(newann); // annotation was
2434 // duplicated earlier
2435 // TODO JAL-1145 graphGroups are not updated for sequence
2436 // annotation added to several views. This may cause
2438 alview[avnum].setAnnotationIndex(newann, a);
2443 buildSortByAnnotationScoresMenu();
2445 viewport.firePropertyChange("alignment", null,
2446 alignment.getSequences());
2447 if (alignPanels != null)
2449 for (AlignmentPanel ap : alignPanels)
2451 ap.validateAnnotationDimensions(false);
2456 alignPanel.validateAnnotationDimensions(false);
2462 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2464 String newtitle = new String("Copied sequences");
2466 if (Desktop.jalviewClipboard != null
2467 && Desktop.jalviewClipboard[2] != null)
2469 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2470 af.viewport.setHiddenColumns(hc);
2473 // >>>This is a fix for the moment, until a better solution is
2475 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2476 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2477 .getFeatureRenderer());
2479 // TODO: maintain provenance of an alignment, rather than just make the
2480 // title a concatenation of operations.
2483 if (title.startsWith("Copied sequences"))
2489 newtitle = newtitle.concat("- from " + title);
2494 newtitle = new String("Pasted sequences");
2497 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2502 } catch (Exception ex)
2504 ex.printStackTrace();
2505 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2506 // could be anything being pasted in here
2512 protected void expand_newalign(ActionEvent e)
2516 AlignmentI alignment = AlignmentUtils
2517 .expandContext(getViewport().getAlignment(), -1);
2518 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2520 String newtitle = new String("Flanking alignment");
2522 if (Desktop.jalviewClipboard != null
2523 && Desktop.jalviewClipboard[2] != null)
2525 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2526 af.viewport.setHiddenColumns(hc);
2529 // >>>This is a fix for the moment, until a better solution is
2531 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2532 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2533 .getFeatureRenderer());
2535 // TODO: maintain provenance of an alignment, rather than just make the
2536 // title a concatenation of operations.
2538 if (title.startsWith("Copied sequences"))
2544 newtitle = newtitle.concat("- from " + title);
2548 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2550 } catch (Exception ex)
2552 ex.printStackTrace();
2553 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2554 // could be anything being pasted in here
2555 } catch (OutOfMemoryError oom)
2557 new OOMWarning("Viewing flanking region of alignment", oom);
2562 * Action Cut (delete and copy) the selected region
2565 protected void cut_actionPerformed()
2567 copy_actionPerformed();
2568 delete_actionPerformed();
2572 * Performs menu option to Delete the currently selected region
2575 protected void delete_actionPerformed()
2578 SequenceGroup sg = viewport.getSelectionGroup();
2584 Runnable okAction = () -> {
2585 SequenceI[] cut = sg.getSequences()
2586 .toArray(new SequenceI[sg.getSize()]);
2588 addHistoryItem(new EditCommand(
2589 MessageManager.getString("label.cut_sequences"), Action.CUT,
2590 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2591 viewport.getAlignment()));
2593 viewport.setSelectionGroup(null);
2594 viewport.sendSelection();
2595 viewport.getAlignment().deleteGroup(sg);
2597 viewport.firePropertyChange("alignment", null,
2598 viewport.getAlignment().getSequences());
2599 if (viewport.getAlignment().getHeight() < 1)
2603 AlignFrame.this.setClosed(true);
2604 } catch (Exception ex)
2611 * If the cut affects all sequences, prompt for confirmation
2613 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2615 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2616 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2617 if (wholeHeight && wholeWidth)
2619 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2620 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2621 Object[] options = new Object[] {
2622 MessageManager.getString("action.ok"),
2623 MessageManager.getString("action.cancel") };
2624 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2625 MessageManager.getString("label.delete_all"),
2626 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2627 options, options[0]);
2634 } catch (Exception e)
2636 e.printStackTrace();
2648 protected void deleteGroups_actionPerformed(ActionEvent e)
2650 if (avc.deleteGroups())
2652 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2653 alignPanel.updateAnnotation();
2654 alignPanel.paintAlignment(true, true);
2665 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2667 SequenceGroup sg = new SequenceGroup(
2668 viewport.getAlignment().getSequences());
2670 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2671 viewport.setSelectionGroup(sg);
2672 viewport.isSelectionGroupChanged(true);
2673 viewport.sendSelection();
2674 // JAL-2034 - should delegate to
2675 // alignPanel to decide if overview needs
2677 alignPanel.paintAlignment(false, false);
2678 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2688 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2690 if (viewport.cursorMode)
2692 alignPanel.getSeqPanel().keyboardNo1 = null;
2693 alignPanel.getSeqPanel().keyboardNo2 = null;
2695 viewport.setSelectionGroup(null);
2696 viewport.getColumnSelection().clear();
2697 viewport.setSearchResults(null);
2698 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2699 // JAL-2034 - should delegate to
2700 // alignPanel to decide if overview needs
2702 alignPanel.paintAlignment(false, false);
2703 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2704 viewport.sendSelection();
2714 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2716 SequenceGroup sg = viewport.getSelectionGroup();
2720 selectAllSequenceMenuItem_actionPerformed(null);
2725 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2727 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2729 // JAL-2034 - should delegate to
2730 // alignPanel to decide if overview needs
2733 alignPanel.paintAlignment(true, false);
2734 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2735 viewport.sendSelection();
2739 public void invertColSel_actionPerformed(ActionEvent e)
2741 viewport.invertColumnSelection();
2742 alignPanel.paintAlignment(true, false);
2743 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2744 viewport.sendSelection();
2754 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2756 trimAlignment(true);
2766 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2768 trimAlignment(false);
2771 void trimAlignment(boolean trimLeft)
2773 ColumnSelection colSel = viewport.getColumnSelection();
2776 if (!colSel.isEmpty())
2780 column = colSel.getMin();
2784 column = colSel.getMax();
2788 if (viewport.getSelectionGroup() != null)
2790 seqs = viewport.getSelectionGroup()
2791 .getSequencesAsArray(viewport.getHiddenRepSequences());
2795 seqs = viewport.getAlignment().getSequencesArray();
2798 TrimRegionCommand trimRegion;
2801 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2802 column, viewport.getAlignment());
2803 viewport.getRanges().setStartRes(0);
2807 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2808 column, viewport.getAlignment());
2811 setStatus(MessageManager.formatMessage("label.removed_columns",
2813 { Integer.valueOf(trimRegion.getSize()).toString() }));
2815 addHistoryItem(trimRegion);
2817 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2819 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2820 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2822 viewport.getAlignment().deleteGroup(sg);
2826 viewport.firePropertyChange("alignment", null,
2827 viewport.getAlignment().getSequences());
2838 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2840 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2843 if (viewport.getSelectionGroup() != null)
2845 seqs = viewport.getSelectionGroup()
2846 .getSequencesAsArray(viewport.getHiddenRepSequences());
2847 start = viewport.getSelectionGroup().getStartRes();
2848 end = viewport.getSelectionGroup().getEndRes();
2852 seqs = viewport.getAlignment().getSequencesArray();
2855 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2856 "Remove Gapped Columns", seqs, start, end,
2857 viewport.getAlignment());
2859 addHistoryItem(removeGapCols);
2861 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2863 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2865 // This is to maintain viewport position on first residue
2866 // of first sequence
2867 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2868 ViewportRanges ranges = viewport.getRanges();
2869 int startRes = seq.findPosition(ranges.getStartRes());
2870 // ShiftList shifts;
2871 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2872 // edit.alColumnChanges=shifts.getInverse();
2873 // if (viewport.hasHiddenColumns)
2874 // viewport.getColumnSelection().compensateForEdits(shifts);
2875 ranges.setStartRes(seq.findIndex(startRes) - 1);
2876 viewport.firePropertyChange("alignment", null,
2877 viewport.getAlignment().getSequences());
2888 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2890 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2893 if (viewport.getSelectionGroup() != null)
2895 seqs = viewport.getSelectionGroup()
2896 .getSequencesAsArray(viewport.getHiddenRepSequences());
2897 start = viewport.getSelectionGroup().getStartRes();
2898 end = viewport.getSelectionGroup().getEndRes();
2902 seqs = viewport.getAlignment().getSequencesArray();
2905 // This is to maintain viewport position on first residue
2906 // of first sequence
2907 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2908 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2910 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2911 viewport.getAlignment()));
2913 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2915 viewport.firePropertyChange("alignment", null,
2916 viewport.getAlignment().getSequences());
2927 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2929 viewport.setPadGaps(padGapsMenuitem.isSelected());
2930 viewport.firePropertyChange("alignment", null,
2931 viewport.getAlignment().getSequences());
2935 * Opens a Finder dialog
2940 public void findMenuItem_actionPerformed(ActionEvent e)
2942 new Finder(alignPanel, false, null);
2946 * Create a new view of the current alignment.
2949 public void newView_actionPerformed(ActionEvent e)
2951 newView(null, true);
2955 * Creates and shows a new view of the current alignment.
2958 * title of newly created view; if null, one will be generated
2959 * @param copyAnnotation
2960 * if true then duplicate all annnotation, groups and settings
2961 * @return new alignment panel, already displayed.
2963 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2966 * Create a new AlignmentPanel (with its own, new Viewport)
2968 AlignmentPanel newap = new jalview.project.Jalview2XML()
2969 .copyAlignPanel(alignPanel);
2970 if (!copyAnnotation)
2973 * remove all groups and annotation except for the automatic stuff
2975 newap.av.getAlignment().deleteAllGroups();
2976 newap.av.getAlignment().deleteAllAnnotations(false);
2979 newap.av.setGatherViewsHere(false);
2981 if (viewport.getViewName() == null)
2983 viewport.setViewName(
2984 MessageManager.getString("label.view_name_original"));
2988 * Views share the same edits undo and redo stacks
2990 newap.av.setHistoryList(viewport.getHistoryList());
2991 newap.av.setRedoList(viewport.getRedoList());
2994 * copy any visualisation settings that are not saved in the project
2996 newap.av.setColourAppliesToAllGroups(
2997 viewport.getColourAppliesToAllGroups());
3000 * Views share the same mappings; need to deregister any new mappings
3001 * created by copyAlignPanel, and register the new reference to the shared
3004 newap.av.replaceMappings(viewport.getAlignment());
3007 * start up cDNA consensus (if applicable) now mappings are in place
3009 if (newap.av.initComplementConsensus())
3011 newap.refresh(true); // adjust layout of annotations
3014 newap.av.setViewName(getNewViewName(viewTitle));
3016 addAlignmentPanel(newap, true);
3017 newap.alignmentChanged();
3019 if (alignPanels.size() == 2)
3021 viewport.setGatherViewsHere(true);
3023 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3029 * Make a new name for the view, ensuring it is unique within the current
3030 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3031 * these now use viewId. Unique view names are still desirable for usability.)
3036 protected String getNewViewName(String viewTitle)
3038 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3039 boolean addFirstIndex = false;
3040 if (viewTitle == null || viewTitle.trim().length() == 0)
3042 viewTitle = MessageManager.getString("action.view");
3043 addFirstIndex = true;
3047 index = 1;// we count from 1 if given a specific name
3049 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3051 List<Component> comps = PaintRefresher.components
3052 .get(viewport.getSequenceSetId());
3054 List<String> existingNames = getExistingViewNames(comps);
3056 while (existingNames.contains(newViewName))
3058 newViewName = viewTitle + " " + (++index);
3064 * Returns a list of distinct view names found in the given list of
3065 * components. View names are held on the viewport of an AlignmentPanel.
3070 protected List<String> getExistingViewNames(List<Component> comps)
3072 List<String> existingNames = new ArrayList<>();
3073 for (Component comp : comps)
3075 if (comp instanceof AlignmentPanel)
3077 AlignmentPanel ap = (AlignmentPanel) comp;
3078 if (!existingNames.contains(ap.av.getViewName()))
3080 existingNames.add(ap.av.getViewName());
3084 return existingNames;
3088 * Explode tabbed views into separate windows.
3091 public void expandViews_actionPerformed(ActionEvent e)
3093 Desktop.explodeViews(this);
3097 * Gather views in separate windows back into a tabbed presentation.
3100 public void gatherViews_actionPerformed(ActionEvent e)
3102 Desktop.instance.gatherViews(this);
3112 public void font_actionPerformed(ActionEvent e)
3114 new FontChooser(alignPanel);
3124 protected void seqLimit_actionPerformed(ActionEvent e)
3126 viewport.setShowJVSuffix(seqLimits.isSelected());
3128 alignPanel.getIdPanel().getIdCanvas()
3129 .setPreferredSize(alignPanel.calculateIdWidth());
3130 alignPanel.paintAlignment(true, false);
3134 public void idRightAlign_actionPerformed(ActionEvent e)
3136 viewport.setRightAlignIds(idRightAlign.isSelected());
3137 alignPanel.paintAlignment(false, false);
3141 public void centreColumnLabels_actionPerformed(ActionEvent e)
3143 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3144 alignPanel.paintAlignment(false, false);
3150 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3153 protected void followHighlight_actionPerformed()
3156 * Set the 'follow' flag on the Viewport (and scroll to position if now
3159 final boolean state = this.followHighlightMenuItem.getState();
3160 viewport.setFollowHighlight(state);
3163 alignPanel.scrollToPosition(viewport.getSearchResults());
3174 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3176 viewport.setColourText(colourTextMenuItem.isSelected());
3177 alignPanel.paintAlignment(false, false);
3187 public void wrapMenuItem_actionPerformed(ActionEvent e)
3189 setWrapFormat(wrapMenuItem.isSelected(), false);
3192 public void setWrapFormat(boolean b, boolean setMenuItem)
3194 scaleAbove.setVisible(b);
3195 scaleLeft.setVisible(b);
3196 scaleRight.setVisible(b);
3197 viewport.setWrapAlignment(b);
3198 alignPanel.updateLayout();
3201 wrapMenuItem.setSelected(b);
3206 public void showAllSeqs_actionPerformed(ActionEvent e)
3208 viewport.showAllHiddenSeqs();
3212 public void showAllColumns_actionPerformed(ActionEvent e)
3214 viewport.showAllHiddenColumns();
3215 alignPanel.paintAlignment(true, true);
3216 viewport.sendSelection();
3220 public void hideSelSequences_actionPerformed(ActionEvent e)
3222 viewport.hideAllSelectedSeqs();
3226 * called by key handler and the hide all/show all menu items
3231 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3234 boolean hide = false;
3235 SequenceGroup sg = viewport.getSelectionGroup();
3236 if (!toggleSeqs && !toggleCols)
3238 // Hide everything by the current selection - this is a hack - we do the
3239 // invert and then hide
3240 // first check that there will be visible columns after the invert.
3241 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3242 && sg.getStartRes() <= sg.getEndRes()))
3244 // now invert the sequence set, if required - empty selection implies
3245 // that no hiding is required.
3248 invertSequenceMenuItem_actionPerformed(null);
3249 sg = viewport.getSelectionGroup();
3253 viewport.expandColSelection(sg, true);
3254 // finally invert the column selection and get the new sequence
3256 invertColSel_actionPerformed(null);
3263 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3265 hideSelSequences_actionPerformed(null);
3268 else if (!(toggleCols && viewport.hasSelectedColumns()))
3270 showAllSeqs_actionPerformed(null);
3276 if (viewport.hasSelectedColumns())
3278 hideSelColumns_actionPerformed(null);
3281 viewport.setSelectionGroup(sg);
3286 showAllColumns_actionPerformed(null);
3295 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3296 * event.ActionEvent)
3299 public void hideAllButSelection_actionPerformed(ActionEvent e)
3301 toggleHiddenRegions(false, false);
3302 viewport.sendSelection();
3309 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3313 public void hideAllSelection_actionPerformed(ActionEvent e)
3315 SequenceGroup sg = viewport.getSelectionGroup();
3316 viewport.expandColSelection(sg, false);
3317 viewport.hideAllSelectedSeqs();
3318 viewport.hideSelectedColumns();
3319 alignPanel.updateLayout();
3320 alignPanel.paintAlignment(true, true);
3321 viewport.sendSelection();
3328 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3332 public void showAllhidden_actionPerformed(ActionEvent e)
3334 viewport.showAllHiddenColumns();
3335 viewport.showAllHiddenSeqs();
3336 alignPanel.paintAlignment(true, true);
3337 viewport.sendSelection();
3341 public void hideSelColumns_actionPerformed(ActionEvent e)
3343 viewport.hideSelectedColumns();
3344 alignPanel.updateLayout();
3345 alignPanel.paintAlignment(true, true);
3346 viewport.sendSelection();
3350 public void hiddenMarkers_actionPerformed(ActionEvent e)
3352 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3363 protected void scaleAbove_actionPerformed(ActionEvent e)
3365 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3366 alignPanel.updateLayout();
3367 alignPanel.paintAlignment(true, false);
3377 protected void scaleLeft_actionPerformed(ActionEvent e)
3379 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3380 alignPanel.updateLayout();
3381 alignPanel.paintAlignment(true, false);
3391 protected void scaleRight_actionPerformed(ActionEvent e)
3393 viewport.setScaleRightWrapped(scaleRight.isSelected());
3394 alignPanel.updateLayout();
3395 alignPanel.paintAlignment(true, false);
3405 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3407 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3408 alignPanel.paintAlignment(false, false);
3418 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3420 viewport.setShowText(viewTextMenuItem.isSelected());
3421 alignPanel.paintAlignment(false, false);
3431 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3433 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3434 alignPanel.paintAlignment(false, false);
3437 public FeatureSettings featureSettings;
3440 public FeatureSettingsControllerI getFeatureSettingsUI()
3442 return featureSettings;
3446 public void featureSettings_actionPerformed(ActionEvent e)
3448 showFeatureSettingsUI();
3452 public FeatureSettingsControllerI showFeatureSettingsUI()
3454 if (featureSettings != null)
3456 featureSettings.closeOldSettings();
3457 featureSettings = null;
3459 if (!showSeqFeatures.isSelected())
3461 // make sure features are actually displayed
3462 showSeqFeatures.setSelected(true);
3463 showSeqFeatures_actionPerformed(null);
3465 featureSettings = new FeatureSettings(this);
3466 return featureSettings;
3470 * Set or clear 'Show Sequence Features'
3476 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3478 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3479 alignPanel.paintAlignment(true, true);
3483 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3484 * the annotations panel as a whole.
3486 * The options to show/hide all annotations should be enabled when the panel
3487 * is shown, and disabled when the panel is hidden.
3492 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3494 final boolean setVisible = annotationPanelMenuItem.isSelected();
3495 viewport.setShowAnnotation(setVisible);
3496 this.showAllSeqAnnotations.setEnabled(setVisible);
3497 this.hideAllSeqAnnotations.setEnabled(setVisible);
3498 this.showAllAlAnnotations.setEnabled(setVisible);
3499 this.hideAllAlAnnotations.setEnabled(setVisible);
3500 alignPanel.updateLayout();
3504 public void alignmentProperties()
3507 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3510 String content = MessageManager.formatMessage("label.html_content",
3512 { contents.toString() });
3515 if (Platform.isJS())
3517 JLabel textLabel = new JLabel();
3518 textLabel.setText(content);
3519 textLabel.setBackground(Color.WHITE);
3521 pane = new JPanel(new BorderLayout());
3522 ((JPanel) pane).setOpaque(true);
3523 pane.setBackground(Color.WHITE);
3524 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3533 JEditorPane editPane = new JEditorPane("text/html", "");
3534 editPane.setEditable(false);
3535 editPane.setText(content);
3539 JInternalFrame frame = new JInternalFrame();
3540 frame.setFrameIcon(null);
3541 frame.getContentPane().add(new JScrollPane(pane));
3543 Desktop.addInternalFrame(frame, MessageManager
3544 .formatMessage("label.alignment_properties", new Object[]
3545 { getTitle() }), 500, 400);
3549 * Opens an Overview panel for the alignment, unless one is open already
3554 public void overviewMenuItem_actionPerformed(ActionEvent e)
3556 boolean showHiddenRegions = Cache
3557 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3558 openOverviewPanel(showHiddenRegions);
3561 public OverviewPanel openOverviewPanel(boolean showHidden)
3563 if (alignPanel.overviewPanel != null)
3565 return alignPanel.overviewPanel;
3567 JInternalFrame frame = new JInternalFrame();
3568 frame.setFrameIcon(null);
3569 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3571 frame.setContentPane(overview);
3572 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3573 frame.getHeight(), true, true);
3575 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3576 final AlignmentPanel thePanel = this.alignPanel;
3577 frame.addInternalFrameListener(
3578 new javax.swing.event.InternalFrameAdapter()
3581 public void internalFrameClosed(
3582 javax.swing.event.InternalFrameEvent evt)
3585 thePanel.setOverviewPanel(null);
3588 if (getKeyListeners().length > 0)
3590 frame.addKeyListener(getKeyListeners()[0]);
3593 alignPanel.setOverviewPanel(overview);
3594 alignPanel.setOverviewTitle(this);
3600 public void textColour_actionPerformed()
3602 new TextColourChooser().chooseColour(alignPanel, null);
3606 * public void covariationColour_actionPerformed() {
3608 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3612 public void annotationColour_actionPerformed()
3614 new AnnotationColourChooser(viewport, alignPanel);
3618 public void annotationColumn_actionPerformed(ActionEvent e)
3620 new AnnotationColumnChooser(viewport, alignPanel);
3624 * Action on the user checking or unchecking the option to apply the selected
3625 * colour scheme to all groups. If unchecked, groups may have their own
3626 * independent colour schemes.
3631 public void applyToAllGroups_actionPerformed(boolean selected)
3633 viewport.setColourAppliesToAllGroups(selected);
3637 * Action on user selecting a colour from the colour menu
3640 * the name (not the menu item label!) of the colour scheme
3643 public void changeColour_actionPerformed(String name)
3646 * 'User Defined' opens a panel to configure or load a
3647 * user-defined colour scheme
3649 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3651 new UserDefinedColours(alignPanel);
3656 * otherwise set the chosen colour scheme (or null for 'None')
3658 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3659 viewport, viewport.getAlignment(),
3660 viewport.getHiddenRepSequences());
3665 * Actions on setting or changing the alignment colour scheme
3670 public void changeColour(ColourSchemeI cs)
3672 // TODO: pull up to controller method
3673 ColourMenuHelper.setColourSelected(colourMenu, cs);
3675 viewport.setGlobalColourScheme(cs);
3677 alignPanel.paintAlignment(true, true);
3681 * Show the PID threshold slider panel
3684 protected void modifyPID_actionPerformed()
3686 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3687 alignPanel.getViewName());
3688 SliderPanel.showPIDSlider();
3692 * Show the Conservation slider panel
3695 protected void modifyConservation_actionPerformed()
3697 SliderPanel.setConservationSlider(alignPanel,
3698 viewport.getResidueShading(), alignPanel.getViewName());
3699 SliderPanel.showConservationSlider();
3703 * Action on selecting or deselecting (Colour) By Conservation
3706 public void conservationMenuItem_actionPerformed(boolean selected)
3708 modifyConservation.setEnabled(selected);
3709 viewport.setConservationSelected(selected);
3710 viewport.getResidueShading().setConservationApplied(selected);
3712 changeColour(viewport.getGlobalColourScheme());
3715 modifyConservation_actionPerformed();
3719 SliderPanel.hideConservationSlider();
3724 * Action on selecting or deselecting (Colour) Above PID Threshold
3727 public void abovePIDThreshold_actionPerformed(boolean selected)
3729 modifyPID.setEnabled(selected);
3730 viewport.setAbovePIDThreshold(selected);
3733 viewport.getResidueShading().setThreshold(0,
3734 viewport.isIgnoreGapsConsensus());
3737 changeColour(viewport.getGlobalColourScheme());
3740 modifyPID_actionPerformed();
3744 SliderPanel.hidePIDSlider();
3755 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3757 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3758 AlignmentSorter.sortByPID(viewport.getAlignment(),
3759 viewport.getAlignment().getSequenceAt(0));
3760 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3761 viewport.getAlignment()));
3762 alignPanel.paintAlignment(true, false);
3772 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3774 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3775 AlignmentSorter.sortByID(viewport.getAlignment());
3777 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3778 alignPanel.paintAlignment(true, false);
3788 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3790 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3791 AlignmentSorter.sortByLength(viewport.getAlignment());
3792 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3793 viewport.getAlignment()));
3794 alignPanel.paintAlignment(true, false);
3804 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3806 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3807 AlignmentSorter.sortByGroup(viewport.getAlignment());
3808 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3809 viewport.getAlignment()));
3811 alignPanel.paintAlignment(true, false);
3821 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3823 new RedundancyPanel(alignPanel, this);
3833 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3835 if ((viewport.getSelectionGroup() == null)
3836 || (viewport.getSelectionGroup().getSize() < 2))
3838 JvOptionPane.showInternalMessageDialog(this,
3839 MessageManager.getString(
3840 "label.you_must_select_least_two_sequences"),
3841 MessageManager.getString("label.invalid_selection"),
3842 JvOptionPane.WARNING_MESSAGE);
3846 JInternalFrame frame = new JInternalFrame();
3847 frame.setFrameIcon(null);
3848 frame.setContentPane(new PairwiseAlignPanel(viewport));
3849 Desktop.addInternalFrame(frame,
3850 MessageManager.getString("action.pairwise_alignment"), 600,
3856 public void autoCalculate_actionPerformed(ActionEvent e)
3858 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3859 if (viewport.autoCalculateConsensus)
3861 viewport.firePropertyChange("alignment", null,
3862 viewport.getAlignment().getSequences());
3867 public void sortByTreeOption_actionPerformed(ActionEvent e)
3869 viewport.sortByTree = sortByTree.isSelected();
3873 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3875 viewport.followSelection = listenToViewSelections.isSelected();
3879 * Constructs a tree panel and adds it to the desktop
3882 * tree type (NJ or AV)
3884 * name of score model used to compute the tree
3886 * parameters for the distance or similarity calculation
3888 void newTreePanel(String type, String modelName,
3889 SimilarityParamsI options)
3891 String frameTitle = "";
3894 boolean onSelection = false;
3895 if (viewport.getSelectionGroup() != null
3896 && viewport.getSelectionGroup().getSize() > 0)
3898 SequenceGroup sg = viewport.getSelectionGroup();
3900 /* Decide if the selection is a column region */
3901 for (SequenceI _s : sg.getSequences())
3903 if (_s.getLength() < sg.getEndRes())
3905 JvOptionPane.showMessageDialog(Desktop.desktop,
3906 MessageManager.getString(
3907 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3908 MessageManager.getString(
3909 "label.sequences_selection_not_aligned"),
3910 JvOptionPane.WARNING_MESSAGE);
3919 if (viewport.getAlignment().getHeight() < 2)
3925 tp = new TreePanel(alignPanel, type, modelName, options);
3926 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3928 frameTitle += " from ";
3930 if (viewport.getViewName() != null)
3932 frameTitle += viewport.getViewName() + " of ";
3935 frameTitle += this.title;
3937 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3948 public void addSortByOrderMenuItem(String title,
3949 final AlignmentOrder order)
3951 final JMenuItem item = new JMenuItem(MessageManager
3952 .formatMessage("action.by_title_param", new Object[]
3955 item.addActionListener(new java.awt.event.ActionListener()
3958 public void actionPerformed(ActionEvent e)
3960 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3962 // TODO: JBPNote - have to map order entries to curent SequenceI
3964 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3966 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3967 viewport.getAlignment()));
3969 alignPanel.paintAlignment(true, false);
3975 * Add a new sort by annotation score menu item
3978 * the menu to add the option to
3980 * the label used to retrieve scores for each sequence on the
3983 public void addSortByAnnotScoreMenuItem(JMenu sort,
3984 final String scoreLabel)
3986 final JMenuItem item = new JMenuItem(scoreLabel);
3988 item.addActionListener(new java.awt.event.ActionListener()
3991 public void actionPerformed(ActionEvent e)
3993 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3994 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3995 viewport.getAlignment());// ,viewport.getSelectionGroup());
3996 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3997 viewport.getAlignment()));
3998 alignPanel.paintAlignment(true, false);
4004 * last hash for alignment's annotation array - used to minimise cost of
4007 protected int _annotationScoreVectorHash;
4010 * search the alignment and rebuild the sort by annotation score submenu the
4011 * last alignment annotation vector hash is stored to minimize cost of
4012 * rebuilding in subsequence calls.
4016 public void buildSortByAnnotationScoresMenu()
4018 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4023 if (viewport.getAlignment().getAlignmentAnnotation()
4024 .hashCode() != _annotationScoreVectorHash)
4026 sortByAnnotScore.removeAll();
4027 // almost certainly a quicker way to do this - but we keep it simple
4028 Hashtable<String, String> scoreSorts = new Hashtable<>();
4029 AlignmentAnnotation aann[];
4030 for (SequenceI sqa : viewport.getAlignment().getSequences())
4032 aann = sqa.getAnnotation();
4033 for (int i = 0; aann != null && i < aann.length; i++)
4035 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4037 scoreSorts.put(aann[i].label, aann[i].label);
4041 Enumeration<String> labels = scoreSorts.keys();
4042 while (labels.hasMoreElements())
4044 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4046 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4049 _annotationScoreVectorHash = viewport.getAlignment()
4050 .getAlignmentAnnotation().hashCode();
4055 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4056 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4057 * call. Listeners are added to remove the menu item when the treePanel is
4058 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4062 public void buildTreeSortMenu()
4064 sortByTreeMenu.removeAll();
4066 List<Component> comps = PaintRefresher.components
4067 .get(viewport.getSequenceSetId());
4068 List<TreePanel> treePanels = new ArrayList<>();
4069 for (Component comp : comps)
4071 if (comp instanceof TreePanel)
4073 treePanels.add((TreePanel) comp);
4077 if (treePanels.size() < 1)
4079 sortByTreeMenu.setVisible(false);
4083 sortByTreeMenu.setVisible(true);
4085 for (final TreePanel tp : treePanels)
4087 final JMenuItem item = new JMenuItem(tp.getTitle());
4088 item.addActionListener(new java.awt.event.ActionListener()
4091 public void actionPerformed(ActionEvent e)
4093 tp.sortByTree_actionPerformed();
4094 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4099 sortByTreeMenu.add(item);
4103 public boolean sortBy(AlignmentOrder alorder, String undoname)
4105 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4106 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4107 if (undoname != null)
4109 addHistoryItem(new OrderCommand(undoname, oldOrder,
4110 viewport.getAlignment()));
4112 alignPanel.paintAlignment(true, false);
4117 * Work out whether the whole set of sequences or just the selected set will
4118 * be submitted for multiple alignment.
4121 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4123 // Now, check we have enough sequences
4124 AlignmentView msa = null;
4126 if ((viewport.getSelectionGroup() != null)
4127 && (viewport.getSelectionGroup().getSize() > 1))
4129 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4130 // some common interface!
4132 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4133 * SequenceI[sz = seqs.getSize(false)];
4135 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4136 * seqs.getSequenceAt(i); }
4138 msa = viewport.getAlignmentView(true);
4140 else if (viewport.getSelectionGroup() != null
4141 && viewport.getSelectionGroup().getSize() == 1)
4143 int option = JvOptionPane.showConfirmDialog(this,
4144 MessageManager.getString("warn.oneseq_msainput_selection"),
4145 MessageManager.getString("label.invalid_selection"),
4146 JvOptionPane.OK_CANCEL_OPTION);
4147 if (option == JvOptionPane.OK_OPTION)
4149 msa = viewport.getAlignmentView(false);
4154 msa = viewport.getAlignmentView(false);
4160 * Decides what is submitted to a secondary structure prediction service: the
4161 * first sequence in the alignment, or in the current selection, or, if the
4162 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4163 * region or the whole alignment. (where the first sequence in the set is the
4164 * one that the prediction will be for).
4166 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4168 AlignmentView seqs = null;
4170 if ((viewport.getSelectionGroup() != null)
4171 && (viewport.getSelectionGroup().getSize() > 0))
4173 seqs = viewport.getAlignmentView(true);
4177 seqs = viewport.getAlignmentView(false);
4179 // limit sequences - JBPNote in future - could spawn multiple prediction
4181 // TODO: viewport.getAlignment().isAligned is a global state - the local
4182 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4183 if (!viewport.getAlignment().isAligned(false))
4185 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4186 // TODO: if seqs.getSequences().length>1 then should really have warned
4200 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4202 // Pick the tree file
4203 JalviewFileChooser chooser = new JalviewFileChooser(
4204 Cache.getProperty("LAST_DIRECTORY"));
4205 chooser.setFileView(new JalviewFileView());
4206 chooser.setDialogTitle(
4207 MessageManager.getString("label.select_newick_like_tree_file"));
4208 chooser.setToolTipText(
4209 MessageManager.getString("label.load_tree_file"));
4211 chooser.setResponseHandler(0, () -> {
4212 String filePath = chooser.getSelectedFile().getPath();
4213 Cache.setProperty("LAST_DIRECTORY", filePath);
4214 NewickFile fin = null;
4217 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4218 DataSourceType.FILE));
4219 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4220 } catch (Exception ex)
4222 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4223 MessageManager.getString("label.problem_reading_tree_file"),
4224 JvOptionPane.WARNING_MESSAGE);
4225 ex.printStackTrace();
4227 if (fin != null && fin.hasWarningMessage())
4229 JvOptionPane.showMessageDialog(Desktop.desktop,
4230 fin.getWarningMessage(),
4232 .getString("label.possible_problem_with_tree_file"),
4233 JvOptionPane.WARNING_MESSAGE);
4236 chooser.showOpenDialog(this);
4239 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4241 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4244 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4245 int h, int x, int y)
4247 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4251 * Add a treeviewer for the tree extracted from a Newick file object to the
4252 * current alignment view
4259 * Associated alignment input data (or null)
4268 * @return TreePanel handle
4270 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4271 AlignmentView input, int w, int h, int x, int y)
4273 TreePanel tp = null;
4279 if (nf.getTree() != null)
4281 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4287 tp.setLocation(x, y);
4290 Desktop.addInternalFrame(tp, treeTitle, w, h);
4292 } catch (Exception ex)
4294 ex.printStackTrace();
4300 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4303 int w = 400, h = 500;
4307 NewickFile fin = new NewickFile(
4308 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4309 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4310 + (aa.sequenceRef != null
4311 ? (" for " + aa.sequenceRef.getDisplayId(false))
4314 showColumnWiseTree(fin, aa, title, w, h, x, y);
4315 } catch (Throwable xx)
4317 Console.error("Unexpected exception showing tree for contact matrix",
4322 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4323 String treeTitle, int w, int h, int x, int y)
4328 if (nf.getTree() == null)
4332 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4338 tp.setLocation(x, y);
4341 Desktop.addInternalFrame(tp, treeTitle, w, h);
4343 } catch (Throwable xx)
4345 Console.error("Unexpected exception showing tree for contact matrix",
4351 private boolean buildingMenu = false;
4354 * Generates menu items and listener event actions for web service clients
4357 public void BuildWebServiceMenu()
4359 while (buildingMenu)
4364 .errPrintln("Waiting for building menu to finish.");
4366 } catch (Exception e)
4370 final AlignFrame me = this;
4371 buildingMenu = true;
4372 new Thread(new Runnable()
4377 final List<JMenuItem> legacyItems = new ArrayList<>();
4380 // jalview.bin.Console.errPrintln("Building ws menu again "
4381 // + Thread.currentThread());
4382 // TODO: add support for context dependent disabling of services based
4384 // alignment and current selection
4385 // TODO: add additional serviceHandle parameter to specify abstract
4387 // class independently of AbstractName
4388 // TODO: add in rediscovery GUI function to restart discoverer
4389 // TODO: group services by location as well as function and/or
4391 // object broker mechanism.
4392 final Vector<JMenu> wsmenu = new Vector<>();
4393 final IProgressIndicator af = me;
4396 * do not i18n these strings - they are hard-coded in class
4397 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4398 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4400 final JMenu msawsmenu = new JMenu("Alignment");
4401 final JMenu secstrmenu = new JMenu(
4402 "Secondary Structure Prediction");
4403 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4404 final JMenu analymenu = new JMenu("Analysis");
4405 final JMenu dismenu = new JMenu("Protein Disorder");
4406 // JAL-940 - only show secondary structure prediction services from
4407 // the legacy server
4408 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4410 Discoverer.services != null && (Discoverer.services.size() > 0))
4412 // TODO: refactor to allow list of AbstractName/Handler bindings to
4414 // stored or retrieved from elsewhere
4415 // No MSAWS used any more:
4416 // Vector msaws = null; // (Vector)
4417 // Discoverer.services.get("MsaWS");
4418 Vector<ServiceHandle> secstrpr = Discoverer.services
4420 if (secstrpr != null)
4422 // Add any secondary structure prediction services
4423 for (int i = 0, j = secstrpr.size(); i < j; i++)
4425 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4426 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4427 .getServiceClient(sh);
4428 int p = secstrmenu.getItemCount();
4429 impl.attachWSMenuEntry(secstrmenu, me);
4430 int q = secstrmenu.getItemCount();
4431 for (int litm = p; litm < q; litm++)
4433 legacyItems.add(secstrmenu.getItem(litm));
4439 // Add all submenus in the order they should appear on the web
4441 wsmenu.add(msawsmenu);
4442 wsmenu.add(secstrmenu);
4443 wsmenu.add(dismenu);
4444 wsmenu.add(analymenu);
4445 // No search services yet
4446 // wsmenu.add(seqsrchmenu);
4448 javax.swing.SwingUtilities.invokeLater(new Runnable()
4455 webService.removeAll();
4456 // first, add discovered services onto the webservices menu
4457 if (wsmenu.size() > 0)
4459 for (int i = 0, j = wsmenu.size(); i < j; i++)
4461 webService.add(wsmenu.get(i));
4466 webService.add(me.webServiceNoServices);
4468 // TODO: move into separate menu builder class.
4470 // logic for 2.11.1.4 is
4471 // always look to see if there is a discover. if there isn't
4472 // we can't show any Jws2 services
4473 // if there are services available, show them - regardless of
4474 // the 'show JWS2 preference'
4475 // if the discoverer is running then say so
4476 // otherwise offer to trigger discovery if 'show JWS2' is not
4478 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4479 if (jws2servs != null)
4481 if (jws2servs.hasServices())
4483 jws2servs.attachWSMenuEntry(webService, me);
4484 for (Jws2Instance sv : jws2servs.getServices())
4486 if (sv.description.toLowerCase(Locale.ROOT)
4489 for (JMenuItem jmi : legacyItems)
4491 jmi.setVisible(false);
4497 if (jws2servs.isRunning())
4499 JMenuItem tm = new JMenuItem(
4500 "Still discovering JABA Services");
4501 tm.setEnabled(false);
4504 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4506 JMenuItem enableJws2 = new JMenuItem(
4507 "Discover Web Services");
4508 enableJws2.setToolTipText(
4509 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4510 enableJws2.setEnabled(true);
4511 enableJws2.addActionListener(new ActionListener()
4515 public void actionPerformed(ActionEvent e)
4517 // start service discoverer, but ignore preference
4518 Desktop.instance.startServiceDiscovery(false,
4522 webService.add(enableJws2);
4526 build_urlServiceMenu(me.webService);
4527 build_fetchdbmenu(webService);
4528 for (JMenu item : wsmenu)
4530 if (item.getItemCount() == 0)
4532 item.setEnabled(false);
4536 item.setEnabled(true);
4539 } catch (Exception e)
4542 "Exception during web service menu building process.",
4547 } catch (Exception e)
4550 buildingMenu = false;
4557 * construct any groupURL type service menu entries.
4561 protected void build_urlServiceMenu(JMenu webService)
4563 // TODO: remove this code when 2.7 is released
4564 // DEBUG - alignmentView
4566 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4567 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4569 * @Override public void actionPerformed(ActionEvent e) {
4570 * jalview.datamodel.AlignmentView
4571 * .testSelectionViews(af.viewport.getAlignment(),
4572 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4574 * }); webService.add(testAlView);
4576 // TODO: refactor to RestClient discoverer and merge menu entries for
4577 // rest-style services with other types of analysis/calculation service
4578 // SHmmr test client - still being implemented.
4579 // DEBUG - alignmentView
4581 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4584 client.attachWSMenuEntry(
4585 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4591 * Searches the alignment sequences for xRefs and builds the Show
4592 * Cross-References menu (formerly called Show Products), with database
4593 * sources for which cross-references are found (protein sources for a
4594 * nucleotide alignment and vice versa)
4596 * @return true if Show Cross-references menu should be enabled
4598 public boolean canShowProducts()
4600 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4601 AlignmentI dataset = viewport.getAlignment().getDataset();
4603 showProducts.removeAll();
4604 final boolean dna = viewport.getAlignment().isNucleotide();
4606 if (seqs == null || seqs.length == 0)
4608 // nothing to see here.
4612 boolean showp = false;
4615 List<String> ptypes = new CrossRef(seqs, dataset)
4616 .findXrefSourcesForSequences(dna);
4618 for (final String source : ptypes)
4621 final AlignFrame af = this;
4622 JMenuItem xtype = new JMenuItem(source);
4623 xtype.addActionListener(new ActionListener()
4626 public void actionPerformed(ActionEvent e)
4628 showProductsFor(af.viewport.getSequenceSelection(), dna,
4632 showProducts.add(xtype);
4634 showProducts.setVisible(showp);
4635 showProducts.setEnabled(showp);
4636 } catch (Exception e)
4639 "canShowProducts threw an exception - please report to help@jalview.org",
4647 * Finds and displays cross-references for the selected sequences (protein
4648 * products for nucleotide sequences, dna coding sequences for peptides).
4651 * the sequences to show cross-references for
4653 * true if from a nucleotide alignment (so showing proteins)
4655 * the database to show cross-references for
4657 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4658 final String source)
4660 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4665 * Construct and display a new frame containing the translation of this
4666 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4669 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4671 AlignmentI al = null;
4674 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4676 al = dna.translateCdna(codeTable);
4677 } catch (Exception ex)
4679 Console.error("Exception during translation. Please report this !",
4681 final String msg = MessageManager.getString(
4682 "label.error_when_translating_sequences_submit_bug_report");
4683 final String errorTitle = MessageManager
4684 .getString("label.implementation_error")
4685 + MessageManager.getString("label.translation_failed");
4686 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4687 JvOptionPane.ERROR_MESSAGE);
4690 if (al == null || al.getHeight() == 0)
4692 final String msg = MessageManager.getString(
4693 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4694 final String errorTitle = MessageManager
4695 .getString("label.translation_failed");
4696 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4697 JvOptionPane.WARNING_MESSAGE);
4701 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4702 af.setFileFormat(this.currentFileFormat);
4703 final String newTitle = MessageManager
4704 .formatMessage("label.translation_of_params", new Object[]
4705 { this.getTitle(), codeTable.getId() });
4706 af.setTitle(newTitle);
4707 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4709 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4710 viewport.openSplitFrame(af, new Alignment(seqs));
4714 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4721 * Set the file format
4725 public void setFileFormat(FileFormatI format)
4727 this.currentFileFormat = format;
4731 * Try to load a features file onto the alignment.
4734 * contents or path to retrieve file or a File object
4736 * access mode of file (see jalview.io.AlignFile)
4737 * @return true if features file was parsed correctly.
4739 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4742 return avc.parseFeaturesFile(file, sourceType,
4743 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4748 public void refreshFeatureUI(boolean enableIfNecessary)
4750 // note - currently this is only still here rather than in the controller
4751 // because of the featureSettings hard reference that is yet to be
4753 if (enableIfNecessary)
4755 viewport.setShowSequenceFeatures(true);
4756 showSeqFeatures.setSelected(true);
4762 public void dragEnter(DropTargetDragEvent evt)
4767 public void dragExit(DropTargetEvent evt)
4772 public void dragOver(DropTargetDragEvent evt)
4777 public void dropActionChanged(DropTargetDragEvent evt)
4782 public void drop(DropTargetDropEvent evt)
4784 // JAL-1552 - acceptDrop required before getTransferable call for
4785 // Java's Transferable for native dnd
4786 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4787 Transferable t = evt.getTransferable();
4789 final AlignFrame thisaf = this;
4790 final List<Object> files = new ArrayList<>();
4791 List<DataSourceType> protocols = new ArrayList<>();
4795 Desktop.transferFromDropTarget(files, protocols, evt, t);
4796 } catch (Exception e)
4798 e.printStackTrace();
4802 new Thread(new Runnable()
4809 // check to see if any of these files have names matching sequences
4812 SequenceIdMatcher idm = new SequenceIdMatcher(
4813 viewport.getAlignment().getSequencesArray());
4815 * Object[] { String,SequenceI}
4817 ArrayList<Object[]> filesmatched = new ArrayList<>();
4818 ArrayList<Object> filesnotmatched = new ArrayList<>();
4819 for (int i = 0; i < files.size(); i++)
4822 Object file = files.get(i);
4823 String fileName = file.toString();
4825 DataSourceType protocol = (file instanceof File
4826 ? DataSourceType.FILE
4827 : FormatAdapter.checkProtocol(fileName));
4828 if (protocol == DataSourceType.FILE)
4831 if (file instanceof File)
4834 Platform.cacheFileData(fl);
4838 fl = new File(fileName);
4840 pdbfn = fl.getName();
4842 else if (protocol == DataSourceType.URL)
4844 URL url = new URL(fileName);
4845 pdbfn = url.getFile();
4847 if (pdbfn.length() > 0)
4849 // attempt to find a match in the alignment
4850 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4851 int l = 0, c = pdbfn.indexOf(".");
4852 while (mtch == null && c != -1)
4857 } while ((c = pdbfn.indexOf(".", l)) > l);
4860 pdbfn = pdbfn.substring(0, l);
4862 mtch = idm.findAllIdMatches(pdbfn);
4869 type = new IdentifyFile().identify(file, protocol);
4870 } catch (Exception ex)
4874 if (type != null && type.isStructureFile())
4876 filesmatched.add(new Object[] { file, protocol, mtch });
4880 // File wasn't named like one of the sequences or wasn't a PDB
4882 filesnotmatched.add(file);
4886 if (filesmatched.size() > 0)
4888 boolean autoAssociate = Cache
4889 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4892 String msg = MessageManager.formatMessage(
4893 "label.automatically_associate_structure_files_with_sequences_same_name",
4895 { Integer.valueOf(filesmatched.size())
4897 String ttl = MessageManager.getString(
4898 "label.automatically_associate_structure_files_by_name");
4899 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4900 ttl, JvOptionPane.YES_NO_OPTION);
4901 autoAssociate = choice == JvOptionPane.YES_OPTION;
4905 for (Object[] fm : filesmatched)
4907 // try and associate
4908 // TODO: may want to set a standard ID naming formalism for
4909 // associating PDB files which have no IDs.
4910 for (SequenceI toassoc : (SequenceI[]) fm[2])
4912 PDBEntry pe = new AssociatePdbFileWithSeq()
4913 .associatePdbWithSeq(fm[0].toString(),
4914 (DataSourceType) fm[1], toassoc, false,
4918 jalview.bin.Console.errPrintln("Associated file : "
4919 + (fm[0].toString()) + " with "
4920 + toassoc.getDisplayId(true));
4924 // TODO: do we need to update overview ? only if features are
4926 alignPanel.paintAlignment(true, false);
4932 * add declined structures as sequences
4934 for (Object[] o : filesmatched)
4936 filesnotmatched.add(o[0]);
4940 if (filesnotmatched.size() > 0)
4942 if (assocfiles > 0 && (Cache.getDefault(
4943 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4944 || JvOptionPane.showConfirmDialog(thisaf,
4945 "<html>" + MessageManager.formatMessage(
4946 "label.ignore_unmatched_dropped_files_info",
4949 filesnotmatched.size())
4952 MessageManager.getString(
4953 "label.ignore_unmatched_dropped_files"),
4954 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4958 for (Object fn : filesnotmatched)
4960 loadJalviewDataFile(fn, null, null, null);
4964 } catch (Exception ex)
4966 ex.printStackTrace();
4974 * Attempt to load a "dropped" file or URL string, by testing in turn for
4976 * <li>an Annotation file</li>
4977 * <li>a JNet file</li>
4978 * <li>a features file</li>
4979 * <li>else try to interpret as an alignment file</li>
4983 * either a filename or a URL string.
4985 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4986 FileFormatI format, SequenceI assocSeq)
4988 // BH 2018 was String file
4991 if (sourceType == null)
4993 sourceType = FormatAdapter.checkProtocol(file);
4995 // if the file isn't identified, or not positively identified as some
4996 // other filetype (PFAM is default unidentified alignment file type) then
4997 // try to parse as annotation.
4998 boolean isAnnotation = (format == null
4999 || FileFormat.Pfam.equals(format))
5000 ? new AnnotationFile().annotateAlignmentView(viewport,
5006 // first see if its a T-COFFEE score file
5007 TCoffeeScoreFile tcf = null;
5010 tcf = new TCoffeeScoreFile(file, sourceType);
5013 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5017 new TCoffeeColourScheme(viewport.getAlignment()));
5018 isAnnotation = true;
5019 setStatus(MessageManager.getString(
5020 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5024 // some problem - if no warning its probable that the ID matching
5025 // process didn't work
5026 JvOptionPane.showMessageDialog(Desktop.desktop,
5027 tcf.getWarningMessage() == null
5028 ? MessageManager.getString(
5029 "label.check_file_matches_sequence_ids_alignment")
5030 : tcf.getWarningMessage(),
5031 MessageManager.getString(
5032 "label.problem_reading_tcoffee_score_file"),
5033 JvOptionPane.WARNING_MESSAGE);
5040 } catch (Exception x)
5043 "Exception when processing data source as T-COFFEE score file",
5049 // try to see if its a JNet 'concise' style annotation file *before*
5051 // try to parse it as a features file
5054 format = new IdentifyFile().identify(file, sourceType);
5056 if (FileFormat.ScoreMatrix == format)
5058 ScoreMatrixFile sm = new ScoreMatrixFile(
5059 new FileParse(file, sourceType));
5061 // todo: i18n this message
5062 setStatus(MessageManager.formatMessage(
5063 "label.successfully_loaded_matrix",
5064 sm.getMatrixName()));
5066 else if (FileFormat.Jnet.equals(format))
5068 JPredFile predictions = new JPredFile(file, sourceType);
5069 new JnetAnnotationMaker();
5070 JnetAnnotationMaker.add_annotation(predictions,
5071 viewport.getAlignment(), 0, false);
5072 viewport.getAlignment().setupJPredAlignment();
5073 isAnnotation = true;
5075 // else if (IdentifyFile.FeaturesFile.equals(format))
5076 else if (FileFormat.Features.equals(format))
5078 if (parseFeaturesFile(file, sourceType))
5080 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5081 if (splitFrame != null)
5083 splitFrame.repaint();
5087 alignPanel.paintAlignment(true, true);
5093 new FileLoader().LoadFile(viewport, file, sourceType, format);
5100 alignPanel.adjustAnnotationHeight();
5101 viewport.updateSequenceIdColours();
5102 buildSortByAnnotationScoresMenu();
5103 alignPanel.paintAlignment(true, true);
5105 } catch (Exception ex)
5107 ex.printStackTrace();
5108 } catch (OutOfMemoryError oom)
5113 } catch (Exception x)
5118 + (sourceType != null
5119 ? (sourceType == DataSourceType.PASTE
5121 : "using " + sourceType + " from "
5125 ? "(parsing as '" + format + "' file)"
5127 oom, Desktop.desktop);
5132 * Method invoked by the ChangeListener on the tabbed pane, in other words
5133 * when a different tabbed pane is selected by the user or programmatically.
5136 public void tabSelectionChanged(int index)
5141 * update current Overview window title (if there is one)
5142 * to add view name "Original" if necessary
5144 alignPanel.setOverviewTitle(this);
5147 * switch panels and set Overview title (if there is one
5148 * because it was opened automatically)
5150 alignPanel = alignPanels.get(index);
5151 alignPanel.setOverviewTitle(this);
5153 viewport = alignPanel.av;
5154 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5155 setMenusFromViewport(viewport);
5156 if (featureSettings != null && featureSettings.isOpen()
5157 && featureSettings.fr.getViewport() != viewport)
5159 if (viewport.isShowSequenceFeatures())
5161 // refresh the featureSettings to reflect UI change
5162 showFeatureSettingsUI();
5166 // close feature settings for this view.
5167 featureSettings.close();
5174 * 'focus' any colour slider that is open to the selected viewport
5176 if (viewport.getConservationSelected())
5178 SliderPanel.setConservationSlider(alignPanel,
5179 viewport.getResidueShading(), alignPanel.getViewName());
5183 SliderPanel.hideConservationSlider();
5185 if (viewport.getAbovePIDThreshold())
5187 SliderPanel.setPIDSliderSource(alignPanel,
5188 viewport.getResidueShading(), alignPanel.getViewName());
5192 SliderPanel.hidePIDSlider();
5196 * If there is a frame linked to this one in a SplitPane, switch it to the
5197 * same view tab index. No infinite recursion of calls should happen, since
5198 * tabSelectionChanged() should not get invoked on setting the selected
5199 * index to an unchanged value. Guard against setting an invalid index
5200 * before the new view peer tab has been created.
5202 final AlignViewportI peer = viewport.getCodingComplement();
5205 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5206 .getAlignPanel().alignFrame;
5207 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5209 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5215 * On right mouse click on view tab, prompt for and set new view name.
5218 public void tabbedPane_mousePressed(MouseEvent e)
5220 if (e.isPopupTrigger())
5222 String msg = MessageManager.getString("label.enter_view_name");
5223 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5224 String reply = JvOptionPane.showInputDialog(msg, ttl);
5228 viewport.setViewName(reply);
5229 // TODO warn if reply is in getExistingViewNames()?
5230 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5235 public AlignViewport getCurrentView()
5241 * Open the dialog for regex description parsing.
5244 protected void extractScores_actionPerformed(ActionEvent e)
5246 ParseProperties pp = new jalview.analysis.ParseProperties(
5247 viewport.getAlignment());
5248 // TODO: verify regex and introduce GUI dialog for version 2.5
5249 // if (pp.getScoresFromDescription("col", "score column ",
5250 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5252 if (pp.getScoresFromDescription("description column",
5253 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5255 buildSortByAnnotationScoresMenu();
5263 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5267 protected void showDbRefs_actionPerformed(ActionEvent e)
5269 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5275 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5279 protected void showNpFeats_actionPerformed(ActionEvent e)
5281 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5285 * find the viewport amongst the tabs in this alignment frame and close that
5290 public boolean closeView(AlignViewportI av)
5294 this.closeMenuItem_actionPerformed(false);
5297 Component[] comp = tabbedPane.getComponents();
5298 for (int i = 0; comp != null && i < comp.length; i++)
5300 if (comp[i] instanceof AlignmentPanel)
5302 if (((AlignmentPanel) comp[i]).av == av)
5305 closeView((AlignmentPanel) comp[i]);
5313 protected void build_fetchdbmenu(JMenu webService)
5315 // Temporary hack - DBRef Fetcher always top level ws entry.
5316 // TODO We probably want to store a sequence database checklist in
5317 // preferences and have checkboxes.. rather than individual sources selected
5319 final JMenu rfetch = new JMenu(
5320 MessageManager.getString("action.fetch_db_references"));
5321 rfetch.setToolTipText(MessageManager.getString(
5322 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5323 webService.add(rfetch);
5325 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5326 MessageManager.getString("option.trim_retrieved_seqs"));
5327 trimrs.setToolTipText(
5328 MessageManager.getString("label.trim_retrieved_sequences"));
5330 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5331 trimrs.addActionListener(new ActionListener()
5334 public void actionPerformed(ActionEvent e)
5336 trimrs.setSelected(trimrs.isSelected());
5337 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5338 Boolean.valueOf(trimrs.isSelected()).toString());
5342 JMenuItem fetchr = new JMenuItem(
5343 MessageManager.getString("label.standard_databases"));
5344 fetchr.setToolTipText(
5345 MessageManager.getString("label.fetch_embl_uniprot"));
5346 fetchr.addActionListener(new ActionListener()
5350 public void actionPerformed(ActionEvent e)
5352 new Thread(new Runnable()
5357 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5358 .getAlignment().isNucleotide();
5359 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5360 alignPanel.av.getSequenceSelection(),
5361 alignPanel.alignFrame, null,
5362 alignPanel.alignFrame.featureSettings, isNucleotide);
5363 dbRefFetcher.addListener(new FetchFinishedListenerI()
5366 public void finished()
5369 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5370 .getFeatureSettingsModels())
5373 alignPanel.av.mergeFeaturesStyle(srcSettings);
5375 AlignFrame.this.setMenusForViewport();
5378 dbRefFetcher.fetchDBRefs(false);
5386 new Thread(new Runnable()
5391 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5392 .getSequenceFetcherSingleton();
5393 javax.swing.SwingUtilities.invokeLater(new Runnable()
5398 String[] dbclasses = sf.getNonAlignmentSources();
5399 List<DbSourceProxy> otherdb;
5400 JMenu dfetch = new JMenu();
5401 JMenu ifetch = new JMenu();
5402 JMenuItem fetchr = null;
5403 int comp = 0, icomp = 0, mcomp = 15;
5404 String mname = null;
5406 for (String dbclass : dbclasses)
5408 otherdb = sf.getSourceProxy(dbclass);
5409 // add a single entry for this class, or submenu allowing 'fetch
5411 if (otherdb == null || otherdb.size() < 1)
5417 mname = "From " + dbclass;
5419 if (otherdb.size() == 1)
5421 final DbSourceProxy[] dassource = otherdb
5422 .toArray(new DbSourceProxy[0]);
5423 DbSourceProxy src = otherdb.get(0);
5424 fetchr = new JMenuItem(src.getDbSource());
5425 fetchr.addActionListener(new ActionListener()
5429 public void actionPerformed(ActionEvent e)
5431 new Thread(new Runnable()
5437 boolean isNucleotide = alignPanel.alignFrame
5438 .getViewport().getAlignment()
5440 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5441 alignPanel.av.getSequenceSelection(),
5442 alignPanel.alignFrame, dassource,
5443 alignPanel.alignFrame.featureSettings,
5446 .addListener(new FetchFinishedListenerI()
5449 public void finished()
5451 FeatureSettingsModelI srcSettings = dassource[0]
5452 .getFeatureColourScheme();
5453 alignPanel.av.mergeFeaturesStyle(
5455 AlignFrame.this.setMenusForViewport();
5458 dbRefFetcher.fetchDBRefs(false);
5464 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5465 MessageManager.formatMessage(
5466 "label.fetch_retrieve_from", new Object[]
5467 { src.getDbName() })));
5473 final DbSourceProxy[] dassource = otherdb
5474 .toArray(new DbSourceProxy[0]);
5476 DbSourceProxy src = otherdb.get(0);
5477 fetchr = new JMenuItem(MessageManager
5478 .formatMessage("label.fetch_all_param", new Object[]
5479 { src.getDbSource() }));
5480 fetchr.addActionListener(new ActionListener()
5483 public void actionPerformed(ActionEvent e)
5485 new Thread(new Runnable()
5491 boolean isNucleotide = alignPanel.alignFrame
5492 .getViewport().getAlignment()
5494 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5495 alignPanel.av.getSequenceSelection(),
5496 alignPanel.alignFrame, dassource,
5497 alignPanel.alignFrame.featureSettings,
5500 .addListener(new FetchFinishedListenerI()
5503 public void finished()
5505 AlignFrame.this.setMenusForViewport();
5508 dbRefFetcher.fetchDBRefs(false);
5514 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5515 MessageManager.formatMessage(
5516 "label.fetch_retrieve_from_all_sources",
5518 { Integer.valueOf(otherdb.size())
5520 src.getDbSource(), src.getDbName() })));
5523 // and then build the rest of the individual menus
5524 ifetch = new JMenu(MessageManager.formatMessage(
5525 "label.source_from_db_source", new Object[]
5526 { src.getDbSource() }));
5528 String imname = null;
5530 for (DbSourceProxy sproxy : otherdb)
5532 String dbname = sproxy.getDbName();
5533 String sname = dbname.length() > 5
5534 ? dbname.substring(0, 5) + "..."
5536 String msname = dbname.length() > 10
5537 ? dbname.substring(0, 10) + "..."
5541 imname = MessageManager
5542 .formatMessage("label.from_msname", new Object[]
5545 fetchr = new JMenuItem(msname);
5546 final DbSourceProxy[] dassrc = { sproxy };
5547 fetchr.addActionListener(new ActionListener()
5551 public void actionPerformed(ActionEvent e)
5553 new Thread(new Runnable()
5559 boolean isNucleotide = alignPanel.alignFrame
5560 .getViewport().getAlignment()
5562 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5563 alignPanel.av.getSequenceSelection(),
5564 alignPanel.alignFrame, dassrc,
5565 alignPanel.alignFrame.featureSettings,
5568 .addListener(new FetchFinishedListenerI()
5571 public void finished()
5573 AlignFrame.this.setMenusForViewport();
5576 dbRefFetcher.fetchDBRefs(false);
5582 fetchr.setToolTipText(
5583 "<html>" + MessageManager.formatMessage(
5584 "label.fetch_retrieve_from", new Object[]
5588 if (++icomp >= mcomp || i == (otherdb.size()))
5590 ifetch.setText(MessageManager.formatMessage(
5591 "label.source_to_target", imname, sname));
5593 ifetch = new JMenu();
5601 if (comp >= mcomp || dbi >= (dbclasses.length))
5603 dfetch.setText(MessageManager.formatMessage(
5604 "label.source_to_target", mname, dbclass));
5606 dfetch = new JMenu();
5619 * Left justify the whole alignment.
5622 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5624 AlignmentI al = viewport.getAlignment();
5626 viewport.firePropertyChange("alignment", null, al);
5630 * Right justify the whole alignment.
5633 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5635 AlignmentI al = viewport.getAlignment();
5637 viewport.firePropertyChange("alignment", null, al);
5641 public void setShowSeqFeatures(boolean b)
5643 showSeqFeatures.setSelected(b);
5644 viewport.setShowSequenceFeatures(b);
5651 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5652 * awt.event.ActionEvent)
5655 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5657 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5658 alignPanel.paintAlignment(false, false);
5665 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5669 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5671 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5672 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5680 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5681 * .event.ActionEvent)
5684 protected void showGroupConservation_actionPerformed(ActionEvent e)
5686 viewport.setShowGroupConservation(showGroupConservation.getState());
5687 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5694 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5695 * .event.ActionEvent)
5698 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5700 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5701 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5708 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5709 * .event.ActionEvent)
5712 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5714 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5715 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5719 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5721 showSequenceLogo.setState(true);
5722 viewport.setShowSequenceLogo(true);
5723 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5724 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5728 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5730 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5737 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5738 * .event.ActionEvent)
5741 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5743 if (avc.makeGroupsFromSelection())
5745 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5746 alignPanel.updateAnnotation();
5747 alignPanel.paintAlignment(true,
5748 viewport.needToUpdateStructureViews());
5752 public void clearAlignmentSeqRep()
5754 // TODO refactor alignmentseqrep to controller
5755 if (viewport.getAlignment().hasSeqrep())
5757 viewport.getAlignment().setSeqrep(null);
5758 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5759 alignPanel.updateAnnotation();
5760 alignPanel.paintAlignment(true, true);
5765 protected void createGroup_actionPerformed(ActionEvent e)
5767 if (avc.createGroup())
5769 if (applyAutoAnnotationSettings.isSelected())
5771 alignPanel.updateAnnotation(true, false);
5773 alignPanel.alignmentChanged();
5778 protected void unGroup_actionPerformed(ActionEvent e)
5782 alignPanel.alignmentChanged();
5787 * make the given alignmentPanel the currently selected tab
5789 * @param alignmentPanel
5791 public void setDisplayedView(AlignmentPanel alignmentPanel)
5793 if (!viewport.getSequenceSetId()
5794 .equals(alignmentPanel.av.getSequenceSetId()))
5796 throw new Error(MessageManager.getString(
5797 "error.implementation_error_cannot_show_view_alignment_frame"));
5799 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5800 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5802 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5807 * Action on selection of menu options to Show or Hide annotations.
5810 * @param forSequences
5811 * update sequence-related annotations
5812 * @param forAlignment
5813 * update non-sequence-related annotations
5816 public void setAnnotationsVisibility(boolean visible,
5817 boolean forSequences, boolean forAlignment)
5819 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5820 .getAlignmentAnnotation();
5825 for (AlignmentAnnotation aa : anns)
5828 * don't display non-positional annotations on an alignment
5830 if (aa.annotations == null)
5834 boolean apply = (aa.sequenceRef == null && forAlignment)
5835 || (aa.sequenceRef != null && forSequences);
5838 aa.visible = visible;
5841 alignPanel.validateAnnotationDimensions(true);
5842 alignPanel.alignmentChanged();
5846 * Store selected annotation sort order for the view and repaint.
5849 protected void sortAnnotations_actionPerformed()
5851 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5853 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5854 alignPanel.paintAlignment(false, false);
5859 * @return alignment panels in this alignment frame
5861 public List<? extends AlignmentViewPanel> getAlignPanels()
5863 // alignPanels is never null
5864 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5869 * Open a new alignment window, with the cDNA associated with this (protein)
5870 * alignment, aligned as is the protein.
5872 protected void viewAsCdna_actionPerformed()
5874 // TODO no longer a menu action - refactor as required
5875 final AlignmentI alignment = getViewport().getAlignment();
5876 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5877 if (mappings == null)
5881 List<SequenceI> cdnaSeqs = new ArrayList<>();
5882 for (SequenceI aaSeq : alignment.getSequences())
5884 for (AlignedCodonFrame acf : mappings)
5886 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5890 * There is a cDNA mapping for this protein sequence - add to new
5891 * alignment. It will share the same dataset sequence as other mapped
5892 * cDNA (no new mappings need to be created).
5894 final Sequence newSeq = new Sequence(dnaSeq);
5895 newSeq.setDatasetSequence(dnaSeq);
5896 cdnaSeqs.add(newSeq);
5900 if (cdnaSeqs.size() == 0)
5902 // show a warning dialog no mapped cDNA
5905 AlignmentI cdna = new Alignment(
5906 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5907 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5908 AlignFrame.DEFAULT_HEIGHT);
5909 cdna.alignAs(alignment);
5910 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5912 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5913 AlignFrame.DEFAULT_HEIGHT);
5917 * Set visibility of dna/protein complement view (available when shown in a
5923 protected void showComplement_actionPerformed(boolean show)
5925 SplitContainerI sf = getSplitViewContainer();
5928 sf.setComplementVisible(this, show);
5933 * Generate the reverse (optionally complemented) of the selected sequences,
5934 * and add them to the alignment
5937 protected void showReverse_actionPerformed(boolean complement)
5939 AlignmentI al = null;
5942 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5943 al = dna.reverseCdna(complement);
5944 viewport.addAlignment(al, "");
5945 addHistoryItem(new EditCommand(
5946 MessageManager.getString("label.add_sequences"), Action.PASTE,
5947 al.getSequencesArray(), 0, al.getWidth(),
5948 viewport.getAlignment()));
5949 } catch (Exception ex)
5951 jalview.bin.Console.errPrintln(ex.getMessage());
5957 * Try to run a script in the Groovy console, having first ensured that this
5958 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5959 * be targeted at this alignment.
5962 protected void runGroovy_actionPerformed()
5964 Jalview.setCurrentAlignFrame(this);
5965 groovy.ui.Console console = Desktop.getGroovyConsole();
5966 if (console != null)
5970 console.runScript();
5971 } catch (Exception ex)
5973 jalview.bin.Console.errPrintln((ex.toString()));
5974 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5975 MessageManager.getString("label.couldnt_run_groovy_script"),
5976 MessageManager.getString("label.groovy_support_failed"),
5977 JvOptionPane.ERROR_MESSAGE);
5983 .errPrintln("Can't run Groovy script as console not found");
5988 * Hides columns containing (or not containing) a specified feature, provided
5989 * that would not leave all columns hidden
5991 * @param featureType
5992 * @param columnsContaining
5995 public boolean hideFeatureColumns(String featureType,
5996 boolean columnsContaining)
5998 boolean notForHiding = avc.markColumnsContainingFeatures(
5999 columnsContaining, false, false, featureType);
6002 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6003 false, featureType))
6005 getViewport().hideSelectedColumns();
6013 protected void selectHighlightedColumns_actionPerformed(
6014 ActionEvent actionEvent)
6016 // include key modifier check in case user selects from menu
6017 avc.markHighlightedColumns(
6018 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6019 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6020 | ActionEvent.CTRL_MASK)) != 0);
6024 protected void copyHighlightedColumns_actionPerformed(
6025 ActionEvent actionEvent)
6027 avc.copyHighlightedRegionsToClipboard();
6031 * Rebuilds the Colour menu, including any user-defined colours which have
6032 * been loaded either on startup or during the session
6034 public void buildColourMenu()
6036 colourMenu.removeAll();
6038 colourMenu.add(applyToAllGroups);
6039 colourMenu.add(textColour);
6040 colourMenu.addSeparator();
6042 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6043 viewport.getAlignment(), false);
6045 colourMenu.add(annotationColour);
6046 bg.add(annotationColour);
6047 colourMenu.addSeparator();
6048 colourMenu.add(conservationMenuItem);
6049 colourMenu.add(modifyConservation);
6050 colourMenu.add(abovePIDThreshold);
6051 colourMenu.add(modifyPID);
6053 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6054 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6058 * Open a dialog (if not already open) that allows the user to select and
6059 * calculate PCA or Tree analysis
6061 protected void openTreePcaDialog()
6063 if (alignPanel.getCalculationDialog() == null)
6065 new CalculationChooser(AlignFrame.this);
6070 protected void loadVcf_actionPerformed()
6072 JalviewFileChooser chooser = new JalviewFileChooser(
6073 Cache.getProperty("LAST_DIRECTORY"));
6074 chooser.setFileView(new JalviewFileView());
6075 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6076 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6077 final AlignFrame us = this;
6078 chooser.setResponseHandler(0, () -> {
6079 String choice = chooser.getSelectedFile().getPath();
6080 Cache.setProperty("LAST_DIRECTORY", choice);
6081 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6082 new VCFLoader(choice).loadVCF(seqs, us);
6084 chooser.showOpenDialog(null);
6088 private Rectangle lastFeatureSettingsBounds = null;
6091 public void setFeatureSettingsGeometry(Rectangle bounds)
6093 lastFeatureSettingsBounds = bounds;
6097 public Rectangle getFeatureSettingsGeometry()
6099 return lastFeatureSettingsBounds;
6104 class PrintThread extends Thread
6108 public PrintThread(AlignmentPanel ap)
6113 static PageFormat pf;
6118 PrinterJob printJob = PrinterJob.getPrinterJob();
6122 printJob.setPrintable(ap, pf);
6126 printJob.setPrintable(ap);
6129 if (printJob.printDialog())
6134 } catch (Exception PrintException)
6136 PrintException.printStackTrace();