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.nullBitmapImageSizing());
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;
1674 if (alignPanels != null)
1678 if (this.isClosed())
1680 // really close all the windows - otherwise wait till
1681 // setClosed(true) is called
1682 for (int i = 0; i < alignPanels.size(); i++)
1684 AlignmentPanel ap = alignPanels.get(i);
1691 closeView(alignPanel);
1696 if (featureSettings != null && featureSettings.isOpen())
1698 featureSettings.close();
1699 featureSettings = null;
1702 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1703 * be called recursively, with the frame now in 'closed' state
1705 this.setClosed(true);
1707 } catch (Exception ex)
1709 ex.printStackTrace();
1714 * Close the specified panel and close up tabs appropriately.
1716 * @param panelToClose
1718 public void closeView(AlignmentPanel panelToClose)
1720 int index = tabbedPane.getSelectedIndex();
1721 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1722 alignPanels.remove(panelToClose);
1723 panelToClose.closePanel();
1724 panelToClose = null;
1726 tabbedPane.removeTabAt(closedindex);
1727 tabbedPane.validate();
1729 if (index > closedindex || index == tabbedPane.getTabCount())
1731 // modify currently selected tab index if necessary.
1735 this.tabSelectionChanged(index);
1741 void updateEditMenuBar()
1744 if (viewport.getHistoryList().size() > 0)
1746 undoMenuItem.setEnabled(true);
1747 CommandI command = viewport.getHistoryList().peek();
1748 undoMenuItem.setText(MessageManager
1749 .formatMessage("label.undo_command", new Object[]
1750 { command.getDescription() }));
1754 undoMenuItem.setEnabled(false);
1755 undoMenuItem.setText(MessageManager.getString("action.undo"));
1758 if (viewport.getRedoList().size() > 0)
1760 redoMenuItem.setEnabled(true);
1762 CommandI command = viewport.getRedoList().peek();
1763 redoMenuItem.setText(MessageManager
1764 .formatMessage("label.redo_command", new Object[]
1765 { command.getDescription() }));
1769 redoMenuItem.setEnabled(false);
1770 redoMenuItem.setText(MessageManager.getString("action.redo"));
1775 public void addHistoryItem(CommandI command)
1777 if (command.getSize() > 0)
1779 viewport.addToHistoryList(command);
1780 viewport.clearRedoList();
1781 updateEditMenuBar();
1782 viewport.updateHiddenColumns();
1783 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1784 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1785 // viewport.getColumnSelection()
1786 // .getHiddenColumns().size() > 0);
1792 * @return alignment objects for all views
1794 AlignmentI[] getViewAlignments()
1796 if (alignPanels != null)
1798 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1800 for (AlignmentPanel ap : alignPanels)
1802 als[i++] = ap.av.getAlignment();
1806 if (viewport != null)
1808 return new AlignmentI[] { viewport.getAlignment() };
1820 protected void undoMenuItem_actionPerformed(ActionEvent e)
1822 if (viewport.getHistoryList().isEmpty())
1826 CommandI command = viewport.getHistoryList().pop();
1827 viewport.addToRedoList(command);
1828 command.undoCommand(getViewAlignments());
1830 AlignmentViewport originalSource = getOriginatingSource(command);
1831 updateEditMenuBar();
1833 if (originalSource != null)
1835 if (originalSource != viewport)
1838 "Implementation worry: mismatch of viewport origin for undo");
1840 originalSource.updateHiddenColumns();
1841 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1843 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1844 // viewport.getColumnSelection()
1845 // .getHiddenColumns().size() > 0);
1846 originalSource.firePropertyChange("alignment", null,
1847 originalSource.getAlignment().getSequences());
1858 protected void redoMenuItem_actionPerformed(ActionEvent e)
1860 if (viewport.getRedoList().size() < 1)
1865 CommandI command = viewport.getRedoList().pop();
1866 viewport.addToHistoryList(command);
1867 command.doCommand(getViewAlignments());
1869 AlignmentViewport originalSource = getOriginatingSource(command);
1870 updateEditMenuBar();
1872 if (originalSource != null)
1875 if (originalSource != viewport)
1878 "Implementation worry: mismatch of viewport origin for redo");
1880 originalSource.updateHiddenColumns();
1881 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1883 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1884 // viewport.getColumnSelection()
1885 // .getHiddenColumns().size() > 0);
1886 originalSource.firePropertyChange("alignment", null,
1887 originalSource.getAlignment().getSequences());
1891 AlignmentViewport getOriginatingSource(CommandI command)
1893 AlignmentViewport originalSource = null;
1894 // For sequence removal and addition, we need to fire
1895 // the property change event FROM the viewport where the
1896 // original alignment was altered
1897 AlignmentI al = null;
1898 if (command instanceof EditCommand)
1900 EditCommand editCommand = (EditCommand) command;
1901 al = editCommand.getAlignment();
1902 List<Component> comps = PaintRefresher.components
1903 .get(viewport.getSequenceSetId());
1905 for (Component comp : comps)
1907 if (comp instanceof AlignmentPanel)
1909 if (al == ((AlignmentPanel) comp).av.getAlignment())
1911 originalSource = ((AlignmentPanel) comp).av;
1918 if (originalSource == null)
1920 // The original view is closed, we must validate
1921 // the current view against the closed view first
1924 PaintRefresher.validateSequences(al, viewport.getAlignment());
1927 originalSource = viewport;
1930 return originalSource;
1934 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1935 * or the sequence under cursor in keyboard mode
1940 public void moveSelectedSequences(boolean up)
1942 SequenceGroup sg = viewport.getSelectionGroup();
1946 if (viewport.cursorMode)
1948 sg = new SequenceGroup();
1949 sg.addSequence(viewport.getAlignment().getSequenceAt(
1950 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1958 if (sg.getSize() < 1)
1963 // TODO: JAL-3733 - add an event to the undo buffer for this !
1965 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1966 viewport.getHiddenRepSequences(), up);
1967 alignPanel.paintAlignment(true, false);
1970 synchronized void slideSequences(boolean right, int size)
1972 List<SequenceI> sg = new ArrayList<>();
1973 if (viewport.cursorMode)
1975 sg.add(viewport.getAlignment()
1976 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1978 else if (viewport.getSelectionGroup() != null
1979 && viewport.getSelectionGroup().getSize() != viewport
1980 .getAlignment().getHeight())
1982 sg = viewport.getSelectionGroup()
1983 .getSequences(viewport.getHiddenRepSequences());
1991 List<SequenceI> invertGroup = new ArrayList<>();
1993 for (SequenceI seq : viewport.getAlignment().getSequences())
1995 if (!sg.contains(seq))
1997 invertGroup.add(seq);
2001 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
2003 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2004 for (int i = 0; i < invertGroup.size(); i++)
2006 seqs2[i] = invertGroup.get(i);
2009 SlideSequencesCommand ssc;
2012 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2013 viewport.getGapCharacter());
2017 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2018 viewport.getGapCharacter());
2021 int groupAdjustment = 0;
2022 if (ssc.getGapsInsertedBegin() && right)
2024 if (viewport.cursorMode)
2026 alignPanel.getSeqPanel().moveCursor(size, 0);
2030 groupAdjustment = size;
2033 else if (!ssc.getGapsInsertedBegin() && !right)
2035 if (viewport.cursorMode)
2037 alignPanel.getSeqPanel().moveCursor(-size, 0);
2041 groupAdjustment = -size;
2045 if (groupAdjustment != 0)
2047 viewport.getSelectionGroup().setStartRes(
2048 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2049 viewport.getSelectionGroup().setEndRes(
2050 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2054 * just extend the last slide command if compatible; but not if in
2055 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2057 boolean appendHistoryItem = false;
2058 Deque<CommandI> historyList = viewport.getHistoryList();
2059 boolean inSplitFrame = getSplitViewContainer() != null;
2060 if (!inSplitFrame && historyList != null && historyList.size() > 0
2061 && historyList.peek() instanceof SlideSequencesCommand)
2063 appendHistoryItem = ssc.appendSlideCommand(
2064 (SlideSequencesCommand) historyList.peek());
2067 if (!appendHistoryItem)
2069 addHistoryItem(ssc);
2082 protected void copy_actionPerformed()
2084 if (viewport.getSelectionGroup() == null)
2088 // TODO: preserve the ordering of displayed alignment annotation in any
2089 // internal paste (particularly sequence associated annotation)
2090 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2091 String[] omitHidden = null;
2093 if (viewport.hasHiddenColumns())
2095 omitHidden = viewport.getViewAsString(true);
2098 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2099 seqs, omitHidden, null);
2101 StringSelection ss = new StringSelection(output);
2105 jalview.gui.Desktop.internalCopy = true;
2106 // Its really worth setting the clipboard contents
2107 // to empty before setting the large StringSelection!!
2108 Toolkit.getDefaultToolkit().getSystemClipboard()
2109 .setContents(new StringSelection(""), null);
2111 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2113 } catch (OutOfMemoryError er)
2115 new OOMWarning("copying region", er);
2119 HiddenColumns hiddenColumns = null;
2120 if (viewport.hasHiddenColumns())
2122 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2123 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2125 // create new HiddenColumns object with copy of hidden regions
2126 // between startRes and endRes, offset by startRes
2127 hiddenColumns = new HiddenColumns(
2128 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2129 hiddenCutoff, hiddenOffset);
2132 Desktop.jalviewClipboard = new Object[] { seqs,
2133 viewport.getAlignment().getDataset(), hiddenColumns };
2134 setStatus(MessageManager.formatMessage(
2135 "label.copied_sequences_to_clipboard", new Object[]
2136 { Integer.valueOf(seqs.length).toString() }));
2146 protected void pasteNew_actionPerformed(ActionEvent e)
2158 protected void pasteThis_actionPerformed(ActionEvent e)
2164 * Paste contents of Jalview clipboard
2166 * @param newAlignment
2167 * true to paste to a new alignment, otherwise add to this.
2169 void paste(boolean newAlignment)
2171 boolean externalPaste = true;
2174 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2175 Transferable contents = c.getContents(this);
2177 if (contents == null)
2186 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2187 if (str.length() < 1)
2192 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2194 } catch (OutOfMemoryError er)
2196 new OOMWarning("Out of memory pasting sequences!!", er);
2200 SequenceI[] sequences;
2201 boolean annotationAdded = false;
2202 AlignmentI alignment = null;
2204 if (Desktop.jalviewClipboard != null)
2206 // The clipboard was filled from within Jalview, we must use the
2208 // And dataset from the copied alignment
2209 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2210 // be doubly sure that we create *new* sequence objects.
2211 sequences = new SequenceI[newseq.length];
2212 for (int i = 0; i < newseq.length; i++)
2214 sequences[i] = new Sequence(newseq[i]);
2216 alignment = new Alignment(sequences);
2217 externalPaste = false;
2221 // parse the clipboard as an alignment.
2222 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2224 sequences = alignment.getSequencesArray();
2228 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2234 if (Desktop.jalviewClipboard != null)
2236 // dataset is inherited
2237 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2241 // new dataset is constructed
2242 alignment.setDataset(null);
2244 alwidth = alignment.getWidth() + 1;
2248 AlignmentI pastedal = alignment; // preserve pasted alignment object
2249 // Add pasted sequences and dataset into existing alignment.
2250 alignment = viewport.getAlignment();
2251 alwidth = alignment.getWidth() + 1;
2252 // decide if we need to import sequences from an existing dataset
2253 boolean importDs = Desktop.jalviewClipboard != null
2254 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2255 // importDs==true instructs us to copy over new dataset sequences from
2256 // an existing alignment
2257 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2259 // minimum dataset set
2261 for (int i = 0; i < sequences.length; i++)
2265 newDs.addElement(null);
2267 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2269 if (importDs && ds != null)
2271 if (!newDs.contains(ds))
2273 newDs.setElementAt(ds, i);
2274 ds = new Sequence(ds);
2275 // update with new dataset sequence
2276 sequences[i].setDatasetSequence(ds);
2280 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2285 // copy and derive new dataset sequence
2286 sequences[i] = sequences[i].deriveSequence();
2287 alignment.getDataset()
2288 .addSequence(sequences[i].getDatasetSequence());
2289 // TODO: avoid creation of duplicate dataset sequences with a
2290 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2292 alignment.addSequence(sequences[i]); // merges dataset
2296 newDs.clear(); // tidy up
2298 if (alignment.getAlignmentAnnotation() != null)
2300 for (AlignmentAnnotation alan : alignment
2301 .getAlignmentAnnotation())
2303 if (alan.graphGroup > fgroup)
2305 fgroup = alan.graphGroup;
2309 if (pastedal.getAlignmentAnnotation() != null)
2311 // Add any annotation attached to alignment.
2312 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2313 for (int i = 0; i < alann.length; i++)
2315 annotationAdded = true;
2316 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2318 AlignmentAnnotation newann = new AlignmentAnnotation(
2320 if (newann.graphGroup > -1)
2322 if (newGraphGroups.size() <= newann.graphGroup
2323 || newGraphGroups.get(newann.graphGroup) == null)
2325 for (int q = newGraphGroups
2326 .size(); q <= newann.graphGroup; q++)
2328 newGraphGroups.add(q, null);
2330 newGraphGroups.set(newann.graphGroup,
2331 Integer.valueOf(++fgroup));
2333 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2337 newann.padAnnotation(alwidth);
2338 alignment.addAnnotation(newann);
2348 addHistoryItem(new EditCommand(
2349 MessageManager.getString("label.add_sequences"),
2350 Action.PASTE, sequences, 0, alignment.getWidth(),
2353 // Add any annotations attached to sequences
2354 for (int i = 0; i < sequences.length; i++)
2356 if (sequences[i].getAnnotation() != null)
2358 AlignmentAnnotation newann;
2359 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2361 annotationAdded = true;
2362 newann = sequences[i].getAnnotation()[a];
2363 newann.adjustForAlignment();
2364 newann.padAnnotation(alwidth);
2365 if (newann.graphGroup > -1)
2367 if (newann.graphGroup > -1)
2369 if (newGraphGroups.size() <= newann.graphGroup
2370 || newGraphGroups.get(newann.graphGroup) == null)
2372 for (int q = newGraphGroups
2373 .size(); q <= newann.graphGroup; q++)
2375 newGraphGroups.add(q, null);
2377 newGraphGroups.set(newann.graphGroup,
2378 Integer.valueOf(++fgroup));
2380 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2384 // annotation was duplicated earlier
2385 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2386 // take care of contact matrix too
2387 ContactMatrixI cm = sequences[i]
2388 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2391 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2395 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2403 // propagate alignment changed.
2404 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2405 if (annotationAdded)
2407 // Duplicate sequence annotation in all views.
2408 AlignmentI[] alview = this.getViewAlignments();
2409 for (int i = 0; i < sequences.length; i++)
2411 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2416 for (int avnum = 0; avnum < alview.length; avnum++)
2418 if (alview[avnum] != alignment)
2420 // duplicate in a view other than the one with input focus
2421 int avwidth = alview[avnum].getWidth() + 1;
2422 // this relies on sann being preserved after we
2423 // modify the sequence's annotation array for each duplication
2424 for (int a = 0; a < sann.length; a++)
2426 AlignmentAnnotation newann = new AlignmentAnnotation(
2428 sequences[i].addAlignmentAnnotation(newann);
2429 newann.padAnnotation(avwidth);
2430 alview[avnum].addAnnotation(newann); // annotation was
2431 // duplicated earlier
2432 // TODO JAL-1145 graphGroups are not updated for sequence
2433 // annotation added to several views. This may cause
2435 alview[avnum].setAnnotationIndex(newann, a);
2440 buildSortByAnnotationScoresMenu();
2442 viewport.firePropertyChange("alignment", null,
2443 alignment.getSequences());
2444 if (alignPanels != null)
2446 for (AlignmentPanel ap : alignPanels)
2448 ap.validateAnnotationDimensions(false);
2453 alignPanel.validateAnnotationDimensions(false);
2459 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2461 String newtitle = new String("Copied sequences");
2463 if (Desktop.jalviewClipboard != null
2464 && Desktop.jalviewClipboard[2] != null)
2466 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2467 af.viewport.setHiddenColumns(hc);
2470 // >>>This is a fix for the moment, until a better solution is
2472 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2473 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2474 .getFeatureRenderer());
2476 // TODO: maintain provenance of an alignment, rather than just make the
2477 // title a concatenation of operations.
2480 if (title.startsWith("Copied sequences"))
2486 newtitle = newtitle.concat("- from " + title);
2491 newtitle = new String("Pasted sequences");
2494 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2499 } catch (Exception ex)
2501 ex.printStackTrace();
2502 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2503 // could be anything being pasted in here
2509 protected void expand_newalign(ActionEvent e)
2513 AlignmentI alignment = AlignmentUtils
2514 .expandContext(getViewport().getAlignment(), -1);
2515 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2517 String newtitle = new String("Flanking alignment");
2519 if (Desktop.jalviewClipboard != null
2520 && Desktop.jalviewClipboard[2] != null)
2522 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2523 af.viewport.setHiddenColumns(hc);
2526 // >>>This is a fix for the moment, until a better solution is
2528 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2529 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2530 .getFeatureRenderer());
2532 // TODO: maintain provenance of an alignment, rather than just make the
2533 // title a concatenation of operations.
2535 if (title.startsWith("Copied sequences"))
2541 newtitle = newtitle.concat("- from " + title);
2545 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2547 } catch (Exception ex)
2549 ex.printStackTrace();
2550 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2551 // could be anything being pasted in here
2552 } catch (OutOfMemoryError oom)
2554 new OOMWarning("Viewing flanking region of alignment", oom);
2559 * Action Cut (delete and copy) the selected region
2562 protected void cut_actionPerformed()
2564 copy_actionPerformed();
2565 delete_actionPerformed();
2569 * Performs menu option to Delete the currently selected region
2572 protected void delete_actionPerformed()
2575 SequenceGroup sg = viewport.getSelectionGroup();
2581 Runnable okAction = () -> {
2582 SequenceI[] cut = sg.getSequences()
2583 .toArray(new SequenceI[sg.getSize()]);
2585 addHistoryItem(new EditCommand(
2586 MessageManager.getString("label.cut_sequences"), Action.CUT,
2587 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2588 viewport.getAlignment()));
2590 viewport.setSelectionGroup(null);
2591 viewport.sendSelection();
2592 viewport.getAlignment().deleteGroup(sg);
2594 viewport.firePropertyChange("alignment", null,
2595 viewport.getAlignment().getSequences());
2596 if (viewport.getAlignment().getHeight() < 1)
2600 AlignFrame.this.setClosed(true);
2601 } catch (Exception ex)
2608 * If the cut affects all sequences, prompt for confirmation
2610 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2612 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2613 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2614 if (wholeHeight && wholeWidth)
2616 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2617 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2618 Object[] options = new Object[] {
2619 MessageManager.getString("action.ok"),
2620 MessageManager.getString("action.cancel") };
2621 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2622 MessageManager.getString("label.delete_all"),
2623 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2624 options, options[0]);
2631 } catch (Exception e)
2633 e.printStackTrace();
2645 protected void deleteGroups_actionPerformed(ActionEvent e)
2647 if (avc.deleteGroups())
2649 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2650 alignPanel.updateAnnotation();
2651 alignPanel.paintAlignment(true, true);
2662 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2664 SequenceGroup sg = new SequenceGroup(
2665 viewport.getAlignment().getSequences());
2667 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2668 viewport.setSelectionGroup(sg);
2669 viewport.isSelectionGroupChanged(true);
2670 viewport.sendSelection();
2671 // JAL-2034 - should delegate to
2672 // alignPanel to decide if overview needs
2674 alignPanel.paintAlignment(false, false);
2675 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2685 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2687 if (viewport.cursorMode)
2689 alignPanel.getSeqPanel().keyboardNo1 = null;
2690 alignPanel.getSeqPanel().keyboardNo2 = null;
2692 viewport.setSelectionGroup(null);
2693 viewport.getColumnSelection().clear();
2694 viewport.setSearchResults(null);
2695 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2696 // JAL-2034 - should delegate to
2697 // alignPanel to decide if overview needs
2699 alignPanel.paintAlignment(false, false);
2700 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2701 viewport.sendSelection();
2711 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2713 SequenceGroup sg = viewport.getSelectionGroup();
2717 selectAllSequenceMenuItem_actionPerformed(null);
2722 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2724 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2726 // JAL-2034 - should delegate to
2727 // alignPanel to decide if overview needs
2730 alignPanel.paintAlignment(true, false);
2731 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2732 viewport.sendSelection();
2736 public void invertColSel_actionPerformed(ActionEvent e)
2738 viewport.invertColumnSelection();
2739 alignPanel.paintAlignment(true, false);
2740 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2741 viewport.sendSelection();
2751 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2753 trimAlignment(true);
2763 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2765 trimAlignment(false);
2768 void trimAlignment(boolean trimLeft)
2770 ColumnSelection colSel = viewport.getColumnSelection();
2773 if (!colSel.isEmpty())
2777 column = colSel.getMin();
2781 column = colSel.getMax();
2785 if (viewport.getSelectionGroup() != null)
2787 seqs = viewport.getSelectionGroup()
2788 .getSequencesAsArray(viewport.getHiddenRepSequences());
2792 seqs = viewport.getAlignment().getSequencesArray();
2795 TrimRegionCommand trimRegion;
2798 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2799 column, viewport.getAlignment());
2800 viewport.getRanges().setStartRes(0);
2804 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2805 column, viewport.getAlignment());
2808 setStatus(MessageManager.formatMessage("label.removed_columns",
2810 { Integer.valueOf(trimRegion.getSize()).toString() }));
2812 addHistoryItem(trimRegion);
2814 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2816 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2817 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2819 viewport.getAlignment().deleteGroup(sg);
2823 viewport.firePropertyChange("alignment", null,
2824 viewport.getAlignment().getSequences());
2835 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2837 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2840 if (viewport.getSelectionGroup() != null)
2842 seqs = viewport.getSelectionGroup()
2843 .getSequencesAsArray(viewport.getHiddenRepSequences());
2844 start = viewport.getSelectionGroup().getStartRes();
2845 end = viewport.getSelectionGroup().getEndRes();
2849 seqs = viewport.getAlignment().getSequencesArray();
2852 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2853 "Remove Gapped Columns", seqs, start, end,
2854 viewport.getAlignment());
2856 addHistoryItem(removeGapCols);
2858 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2860 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2862 // This is to maintain viewport position on first residue
2863 // of first sequence
2864 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2865 ViewportRanges ranges = viewport.getRanges();
2866 int startRes = seq.findPosition(ranges.getStartRes());
2867 // ShiftList shifts;
2868 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2869 // edit.alColumnChanges=shifts.getInverse();
2870 // if (viewport.hasHiddenColumns)
2871 // viewport.getColumnSelection().compensateForEdits(shifts);
2872 ranges.setStartRes(seq.findIndex(startRes) - 1);
2873 viewport.firePropertyChange("alignment", null,
2874 viewport.getAlignment().getSequences());
2885 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2887 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2890 if (viewport.getSelectionGroup() != null)
2892 seqs = viewport.getSelectionGroup()
2893 .getSequencesAsArray(viewport.getHiddenRepSequences());
2894 start = viewport.getSelectionGroup().getStartRes();
2895 end = viewport.getSelectionGroup().getEndRes();
2899 seqs = viewport.getAlignment().getSequencesArray();
2902 // This is to maintain viewport position on first residue
2903 // of first sequence
2904 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2905 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2907 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2908 viewport.getAlignment()));
2910 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2912 viewport.firePropertyChange("alignment", null,
2913 viewport.getAlignment().getSequences());
2924 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2926 viewport.setPadGaps(padGapsMenuitem.isSelected());
2927 viewport.firePropertyChange("alignment", null,
2928 viewport.getAlignment().getSequences());
2932 * Opens a Finder dialog
2937 public void findMenuItem_actionPerformed(ActionEvent e)
2939 new Finder(alignPanel, false, null);
2943 * Create a new view of the current alignment.
2946 public void newView_actionPerformed(ActionEvent e)
2948 newView(null, true);
2952 * Creates and shows a new view of the current alignment.
2955 * title of newly created view; if null, one will be generated
2956 * @param copyAnnotation
2957 * if true then duplicate all annnotation, groups and settings
2958 * @return new alignment panel, already displayed.
2960 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2963 * Create a new AlignmentPanel (with its own, new Viewport)
2965 AlignmentPanel newap = new jalview.project.Jalview2XML()
2966 .copyAlignPanel(alignPanel);
2967 if (!copyAnnotation)
2970 * remove all groups and annotation except for the automatic stuff
2972 newap.av.getAlignment().deleteAllGroups();
2973 newap.av.getAlignment().deleteAllAnnotations(false);
2976 newap.av.setGatherViewsHere(false);
2978 if (viewport.getViewName() == null)
2980 viewport.setViewName(
2981 MessageManager.getString("label.view_name_original"));
2985 * Views share the same edits undo and redo stacks
2987 newap.av.setHistoryList(viewport.getHistoryList());
2988 newap.av.setRedoList(viewport.getRedoList());
2991 * copy any visualisation settings that are not saved in the project
2993 newap.av.setColourAppliesToAllGroups(
2994 viewport.getColourAppliesToAllGroups());
2997 * Views share the same mappings; need to deregister any new mappings
2998 * created by copyAlignPanel, and register the new reference to the shared
3001 newap.av.replaceMappings(viewport.getAlignment());
3004 * start up cDNA consensus (if applicable) now mappings are in place
3006 if (newap.av.initComplementConsensus())
3008 newap.refresh(true); // adjust layout of annotations
3011 newap.av.setViewName(getNewViewName(viewTitle));
3013 addAlignmentPanel(newap, true);
3014 newap.alignmentChanged();
3016 if (alignPanels.size() == 2)
3018 viewport.setGatherViewsHere(true);
3020 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3026 * Make a new name for the view, ensuring it is unique within the current
3027 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3028 * these now use viewId. Unique view names are still desirable for usability.)
3033 protected String getNewViewName(String viewTitle)
3035 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3036 boolean addFirstIndex = false;
3037 if (viewTitle == null || viewTitle.trim().length() == 0)
3039 viewTitle = MessageManager.getString("action.view");
3040 addFirstIndex = true;
3044 index = 1;// we count from 1 if given a specific name
3046 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3048 List<Component> comps = PaintRefresher.components
3049 .get(viewport.getSequenceSetId());
3051 List<String> existingNames = getExistingViewNames(comps);
3053 while (existingNames.contains(newViewName))
3055 newViewName = viewTitle + " " + (++index);
3061 * Returns a list of distinct view names found in the given list of
3062 * components. View names are held on the viewport of an AlignmentPanel.
3067 protected List<String> getExistingViewNames(List<Component> comps)
3069 List<String> existingNames = new ArrayList<>();
3070 for (Component comp : comps)
3072 if (comp instanceof AlignmentPanel)
3074 AlignmentPanel ap = (AlignmentPanel) comp;
3075 if (!existingNames.contains(ap.av.getViewName()))
3077 existingNames.add(ap.av.getViewName());
3081 return existingNames;
3085 * Explode tabbed views into separate windows.
3088 public void expandViews_actionPerformed(ActionEvent e)
3090 Desktop.explodeViews(this);
3094 * Gather views in separate windows back into a tabbed presentation.
3097 public void gatherViews_actionPerformed(ActionEvent e)
3099 Desktop.instance.gatherViews(this);
3109 public void font_actionPerformed(ActionEvent e)
3111 new FontChooser(alignPanel);
3121 protected void seqLimit_actionPerformed(ActionEvent e)
3123 viewport.setShowJVSuffix(seqLimits.isSelected());
3125 alignPanel.getIdPanel().getIdCanvas()
3126 .setPreferredSize(alignPanel.calculateIdWidth());
3127 alignPanel.paintAlignment(true, false);
3131 public void idRightAlign_actionPerformed(ActionEvent e)
3133 viewport.setRightAlignIds(idRightAlign.isSelected());
3134 alignPanel.paintAlignment(false, false);
3138 public void centreColumnLabels_actionPerformed(ActionEvent e)
3140 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3141 alignPanel.paintAlignment(false, false);
3147 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3150 protected void followHighlight_actionPerformed()
3153 * Set the 'follow' flag on the Viewport (and scroll to position if now
3156 final boolean state = this.followHighlightMenuItem.getState();
3157 viewport.setFollowHighlight(state);
3160 alignPanel.scrollToPosition(viewport.getSearchResults());
3171 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3173 viewport.setColourText(colourTextMenuItem.isSelected());
3174 alignPanel.paintAlignment(false, false);
3184 public void wrapMenuItem_actionPerformed(ActionEvent e)
3186 scaleAbove.setVisible(wrapMenuItem.isSelected());
3187 scaleLeft.setVisible(wrapMenuItem.isSelected());
3188 scaleRight.setVisible(wrapMenuItem.isSelected());
3189 viewport.setWrapAlignment(wrapMenuItem.isSelected());
3190 alignPanel.updateLayout();
3194 public void showAllSeqs_actionPerformed(ActionEvent e)
3196 viewport.showAllHiddenSeqs();
3200 public void showAllColumns_actionPerformed(ActionEvent e)
3202 viewport.showAllHiddenColumns();
3203 alignPanel.paintAlignment(true, true);
3204 viewport.sendSelection();
3208 public void hideSelSequences_actionPerformed(ActionEvent e)
3210 viewport.hideAllSelectedSeqs();
3214 * called by key handler and the hide all/show all menu items
3219 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3222 boolean hide = false;
3223 SequenceGroup sg = viewport.getSelectionGroup();
3224 if (!toggleSeqs && !toggleCols)
3226 // Hide everything by the current selection - this is a hack - we do the
3227 // invert and then hide
3228 // first check that there will be visible columns after the invert.
3229 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3230 && sg.getStartRes() <= sg.getEndRes()))
3232 // now invert the sequence set, if required - empty selection implies
3233 // that no hiding is required.
3236 invertSequenceMenuItem_actionPerformed(null);
3237 sg = viewport.getSelectionGroup();
3241 viewport.expandColSelection(sg, true);
3242 // finally invert the column selection and get the new sequence
3244 invertColSel_actionPerformed(null);
3251 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3253 hideSelSequences_actionPerformed(null);
3256 else if (!(toggleCols && viewport.hasSelectedColumns()))
3258 showAllSeqs_actionPerformed(null);
3264 if (viewport.hasSelectedColumns())
3266 hideSelColumns_actionPerformed(null);
3269 viewport.setSelectionGroup(sg);
3274 showAllColumns_actionPerformed(null);
3283 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3284 * event.ActionEvent)
3287 public void hideAllButSelection_actionPerformed(ActionEvent e)
3289 toggleHiddenRegions(false, false);
3290 viewport.sendSelection();
3297 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3301 public void hideAllSelection_actionPerformed(ActionEvent e)
3303 SequenceGroup sg = viewport.getSelectionGroup();
3304 viewport.expandColSelection(sg, false);
3305 viewport.hideAllSelectedSeqs();
3306 viewport.hideSelectedColumns();
3307 alignPanel.updateLayout();
3308 alignPanel.paintAlignment(true, true);
3309 viewport.sendSelection();
3316 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3320 public void showAllhidden_actionPerformed(ActionEvent e)
3322 viewport.showAllHiddenColumns();
3323 viewport.showAllHiddenSeqs();
3324 alignPanel.paintAlignment(true, true);
3325 viewport.sendSelection();
3329 public void hideSelColumns_actionPerformed(ActionEvent e)
3331 viewport.hideSelectedColumns();
3332 alignPanel.updateLayout();
3333 alignPanel.paintAlignment(true, true);
3334 viewport.sendSelection();
3338 public void hiddenMarkers_actionPerformed(ActionEvent e)
3340 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3351 protected void scaleAbove_actionPerformed(ActionEvent e)
3353 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3354 alignPanel.updateLayout();
3355 alignPanel.paintAlignment(true, false);
3365 protected void scaleLeft_actionPerformed(ActionEvent e)
3367 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3368 alignPanel.updateLayout();
3369 alignPanel.paintAlignment(true, false);
3379 protected void scaleRight_actionPerformed(ActionEvent e)
3381 viewport.setScaleRightWrapped(scaleRight.isSelected());
3382 alignPanel.updateLayout();
3383 alignPanel.paintAlignment(true, false);
3393 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3395 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3396 alignPanel.paintAlignment(false, false);
3406 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3408 viewport.setShowText(viewTextMenuItem.isSelected());
3409 alignPanel.paintAlignment(false, false);
3419 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3421 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3422 alignPanel.paintAlignment(false, false);
3425 public FeatureSettings featureSettings;
3428 public FeatureSettingsControllerI getFeatureSettingsUI()
3430 return featureSettings;
3434 public void featureSettings_actionPerformed(ActionEvent e)
3436 showFeatureSettingsUI();
3440 public FeatureSettingsControllerI showFeatureSettingsUI()
3442 if (featureSettings != null)
3444 featureSettings.closeOldSettings();
3445 featureSettings = null;
3447 if (!showSeqFeatures.isSelected())
3449 // make sure features are actually displayed
3450 showSeqFeatures.setSelected(true);
3451 showSeqFeatures_actionPerformed(null);
3453 featureSettings = new FeatureSettings(this);
3454 return featureSettings;
3458 * Set or clear 'Show Sequence Features'
3464 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3466 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3467 alignPanel.paintAlignment(true, true);
3471 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3472 * the annotations panel as a whole.
3474 * The options to show/hide all annotations should be enabled when the panel
3475 * is shown, and disabled when the panel is hidden.
3480 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3482 final boolean setVisible = annotationPanelMenuItem.isSelected();
3483 viewport.setShowAnnotation(setVisible);
3484 this.showAllSeqAnnotations.setEnabled(setVisible);
3485 this.hideAllSeqAnnotations.setEnabled(setVisible);
3486 this.showAllAlAnnotations.setEnabled(setVisible);
3487 this.hideAllAlAnnotations.setEnabled(setVisible);
3488 alignPanel.updateLayout();
3492 public void alignmentProperties()
3495 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3498 String content = MessageManager.formatMessage("label.html_content",
3500 { contents.toString() });
3503 if (Platform.isJS())
3505 JLabel textLabel = new JLabel();
3506 textLabel.setText(content);
3507 textLabel.setBackground(Color.WHITE);
3509 pane = new JPanel(new BorderLayout());
3510 ((JPanel) pane).setOpaque(true);
3511 pane.setBackground(Color.WHITE);
3512 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3521 JEditorPane editPane = new JEditorPane("text/html", "");
3522 editPane.setEditable(false);
3523 editPane.setText(content);
3527 JInternalFrame frame = new JInternalFrame();
3529 frame.getContentPane().add(new JScrollPane(pane));
3531 Desktop.addInternalFrame(frame, MessageManager
3532 .formatMessage("label.alignment_properties", new Object[]
3533 { getTitle() }), 500, 400);
3537 * Opens an Overview panel for the alignment, unless one is open already
3542 public void overviewMenuItem_actionPerformed(ActionEvent e)
3544 boolean showHiddenRegions = Cache
3545 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3546 openOverviewPanel(showHiddenRegions);
3549 public OverviewPanel openOverviewPanel(boolean showHidden)
3551 if (alignPanel.overviewPanel != null)
3553 return alignPanel.overviewPanel;
3555 JInternalFrame frame = new JInternalFrame();
3556 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3558 frame.setContentPane(overview);
3559 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3560 frame.getHeight(), true, true);
3561 frame.setFrameIcon(null);
3563 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3564 final AlignmentPanel thePanel = this.alignPanel;
3565 frame.addInternalFrameListener(
3566 new javax.swing.event.InternalFrameAdapter()
3569 public void internalFrameClosed(
3570 javax.swing.event.InternalFrameEvent evt)
3573 thePanel.setOverviewPanel(null);
3576 if (getKeyListeners().length > 0)
3578 frame.addKeyListener(getKeyListeners()[0]);
3581 alignPanel.setOverviewPanel(overview);
3582 alignPanel.setOverviewTitle(this);
3588 public void textColour_actionPerformed()
3590 new TextColourChooser().chooseColour(alignPanel, null);
3594 * public void covariationColour_actionPerformed() {
3596 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3600 public void annotationColour_actionPerformed()
3602 new AnnotationColourChooser(viewport, alignPanel);
3606 public void annotationColumn_actionPerformed(ActionEvent e)
3608 new AnnotationColumnChooser(viewport, alignPanel);
3612 * Action on the user checking or unchecking the option to apply the selected
3613 * colour scheme to all groups. If unchecked, groups may have their own
3614 * independent colour schemes.
3619 public void applyToAllGroups_actionPerformed(boolean selected)
3621 viewport.setColourAppliesToAllGroups(selected);
3625 * Action on user selecting a colour from the colour menu
3628 * the name (not the menu item label!) of the colour scheme
3631 public void changeColour_actionPerformed(String name)
3634 * 'User Defined' opens a panel to configure or load a
3635 * user-defined colour scheme
3637 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3639 new UserDefinedColours(alignPanel);
3644 * otherwise set the chosen colour scheme (or null for 'None')
3646 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3647 viewport, viewport.getAlignment(),
3648 viewport.getHiddenRepSequences());
3653 * Actions on setting or changing the alignment colour scheme
3658 public void changeColour(ColourSchemeI cs)
3660 // TODO: pull up to controller method
3661 ColourMenuHelper.setColourSelected(colourMenu, cs);
3663 viewport.setGlobalColourScheme(cs);
3665 alignPanel.paintAlignment(true, true);
3669 * Show the PID threshold slider panel
3672 protected void modifyPID_actionPerformed()
3674 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3675 alignPanel.getViewName());
3676 SliderPanel.showPIDSlider();
3680 * Show the Conservation slider panel
3683 protected void modifyConservation_actionPerformed()
3685 SliderPanel.setConservationSlider(alignPanel,
3686 viewport.getResidueShading(), alignPanel.getViewName());
3687 SliderPanel.showConservationSlider();
3691 * Action on selecting or deselecting (Colour) By Conservation
3694 public void conservationMenuItem_actionPerformed(boolean selected)
3696 modifyConservation.setEnabled(selected);
3697 viewport.setConservationSelected(selected);
3698 viewport.getResidueShading().setConservationApplied(selected);
3700 changeColour(viewport.getGlobalColourScheme());
3703 modifyConservation_actionPerformed();
3707 SliderPanel.hideConservationSlider();
3712 * Action on selecting or deselecting (Colour) Above PID Threshold
3715 public void abovePIDThreshold_actionPerformed(boolean selected)
3717 modifyPID.setEnabled(selected);
3718 viewport.setAbovePIDThreshold(selected);
3721 viewport.getResidueShading().setThreshold(0,
3722 viewport.isIgnoreGapsConsensus());
3725 changeColour(viewport.getGlobalColourScheme());
3728 modifyPID_actionPerformed();
3732 SliderPanel.hidePIDSlider();
3743 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3745 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3746 AlignmentSorter.sortByPID(viewport.getAlignment(),
3747 viewport.getAlignment().getSequenceAt(0));
3748 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3749 viewport.getAlignment()));
3750 alignPanel.paintAlignment(true, false);
3760 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3762 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3763 AlignmentSorter.sortByID(viewport.getAlignment());
3765 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3766 alignPanel.paintAlignment(true, false);
3776 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3778 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3779 AlignmentSorter.sortByLength(viewport.getAlignment());
3780 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3781 viewport.getAlignment()));
3782 alignPanel.paintAlignment(true, false);
3792 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3794 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3795 AlignmentSorter.sortByGroup(viewport.getAlignment());
3796 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3797 viewport.getAlignment()));
3799 alignPanel.paintAlignment(true, false);
3809 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3811 new RedundancyPanel(alignPanel, this);
3821 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3823 if ((viewport.getSelectionGroup() == null)
3824 || (viewport.getSelectionGroup().getSize() < 2))
3826 JvOptionPane.showInternalMessageDialog(this,
3827 MessageManager.getString(
3828 "label.you_must_select_least_two_sequences"),
3829 MessageManager.getString("label.invalid_selection"),
3830 JvOptionPane.WARNING_MESSAGE);
3834 JInternalFrame frame = new JInternalFrame();
3835 frame.setContentPane(new PairwiseAlignPanel(viewport));
3836 Desktop.addInternalFrame(frame,
3837 MessageManager.getString("action.pairwise_alignment"), 600,
3843 public void autoCalculate_actionPerformed(ActionEvent e)
3845 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3846 if (viewport.autoCalculateConsensus)
3848 viewport.firePropertyChange("alignment", null,
3849 viewport.getAlignment().getSequences());
3854 public void sortByTreeOption_actionPerformed(ActionEvent e)
3856 viewport.sortByTree = sortByTree.isSelected();
3860 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3862 viewport.followSelection = listenToViewSelections.isSelected();
3866 * Constructs a tree panel and adds it to the desktop
3869 * tree type (NJ or AV)
3871 * name of score model used to compute the tree
3873 * parameters for the distance or similarity calculation
3875 void newTreePanel(String type, String modelName,
3876 SimilarityParamsI options)
3878 String frameTitle = "";
3881 boolean onSelection = false;
3882 if (viewport.getSelectionGroup() != null
3883 && viewport.getSelectionGroup().getSize() > 0)
3885 SequenceGroup sg = viewport.getSelectionGroup();
3887 /* Decide if the selection is a column region */
3888 for (SequenceI _s : sg.getSequences())
3890 if (_s.getLength() < sg.getEndRes())
3892 JvOptionPane.showMessageDialog(Desktop.desktop,
3893 MessageManager.getString(
3894 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3895 MessageManager.getString(
3896 "label.sequences_selection_not_aligned"),
3897 JvOptionPane.WARNING_MESSAGE);
3906 if (viewport.getAlignment().getHeight() < 2)
3912 tp = new TreePanel(alignPanel, type, modelName, options);
3913 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3915 frameTitle += " from ";
3917 if (viewport.getViewName() != null)
3919 frameTitle += viewport.getViewName() + " of ";
3922 frameTitle += this.title;
3924 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3935 public void addSortByOrderMenuItem(String title,
3936 final AlignmentOrder order)
3938 final JMenuItem item = new JMenuItem(MessageManager
3939 .formatMessage("action.by_title_param", new Object[]
3942 item.addActionListener(new java.awt.event.ActionListener()
3945 public void actionPerformed(ActionEvent e)
3947 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3949 // TODO: JBPNote - have to map order entries to curent SequenceI
3951 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3953 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3954 viewport.getAlignment()));
3956 alignPanel.paintAlignment(true, false);
3962 * Add a new sort by annotation score menu item
3965 * the menu to add the option to
3967 * the label used to retrieve scores for each sequence on the
3970 public void addSortByAnnotScoreMenuItem(JMenu sort,
3971 final String scoreLabel)
3973 final JMenuItem item = new JMenuItem(scoreLabel);
3975 item.addActionListener(new java.awt.event.ActionListener()
3978 public void actionPerformed(ActionEvent e)
3980 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3981 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3982 viewport.getAlignment());// ,viewport.getSelectionGroup());
3983 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3984 viewport.getAlignment()));
3985 alignPanel.paintAlignment(true, false);
3991 * last hash for alignment's annotation array - used to minimise cost of
3994 protected int _annotationScoreVectorHash;
3997 * search the alignment and rebuild the sort by annotation score submenu the
3998 * last alignment annotation vector hash is stored to minimize cost of
3999 * rebuilding in subsequence calls.
4003 public void buildSortByAnnotationScoresMenu()
4005 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4010 if (viewport.getAlignment().getAlignmentAnnotation()
4011 .hashCode() != _annotationScoreVectorHash)
4013 sortByAnnotScore.removeAll();
4014 // almost certainly a quicker way to do this - but we keep it simple
4015 Hashtable<String, String> scoreSorts = new Hashtable<>();
4016 AlignmentAnnotation aann[];
4017 for (SequenceI sqa : viewport.getAlignment().getSequences())
4019 aann = sqa.getAnnotation();
4020 for (int i = 0; aann != null && i < aann.length; i++)
4022 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4024 scoreSorts.put(aann[i].label, aann[i].label);
4028 Enumeration<String> labels = scoreSorts.keys();
4029 while (labels.hasMoreElements())
4031 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4033 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4036 _annotationScoreVectorHash = viewport.getAlignment()
4037 .getAlignmentAnnotation().hashCode();
4042 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4043 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4044 * call. Listeners are added to remove the menu item when the treePanel is
4045 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4049 public void buildTreeSortMenu()
4051 sortByTreeMenu.removeAll();
4053 List<Component> comps = PaintRefresher.components
4054 .get(viewport.getSequenceSetId());
4055 List<TreePanel> treePanels = new ArrayList<>();
4056 for (Component comp : comps)
4058 if (comp instanceof TreePanel)
4060 treePanels.add((TreePanel) comp);
4064 if (treePanels.size() < 1)
4066 sortByTreeMenu.setVisible(false);
4070 sortByTreeMenu.setVisible(true);
4072 for (final TreePanel tp : treePanels)
4074 final JMenuItem item = new JMenuItem(tp.getTitle());
4075 item.addActionListener(new java.awt.event.ActionListener()
4078 public void actionPerformed(ActionEvent e)
4080 tp.sortByTree_actionPerformed();
4081 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4086 sortByTreeMenu.add(item);
4090 public boolean sortBy(AlignmentOrder alorder, String undoname)
4092 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4093 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4094 if (undoname != null)
4096 addHistoryItem(new OrderCommand(undoname, oldOrder,
4097 viewport.getAlignment()));
4099 alignPanel.paintAlignment(true, false);
4104 * Work out whether the whole set of sequences or just the selected set will
4105 * be submitted for multiple alignment.
4108 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4110 // Now, check we have enough sequences
4111 AlignmentView msa = null;
4113 if ((viewport.getSelectionGroup() != null)
4114 && (viewport.getSelectionGroup().getSize() > 1))
4116 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4117 // some common interface!
4119 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4120 * SequenceI[sz = seqs.getSize(false)];
4122 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4123 * seqs.getSequenceAt(i); }
4125 msa = viewport.getAlignmentView(true);
4127 else if (viewport.getSelectionGroup() != null
4128 && viewport.getSelectionGroup().getSize() == 1)
4130 int option = JvOptionPane.showConfirmDialog(this,
4131 MessageManager.getString("warn.oneseq_msainput_selection"),
4132 MessageManager.getString("label.invalid_selection"),
4133 JvOptionPane.OK_CANCEL_OPTION);
4134 if (option == JvOptionPane.OK_OPTION)
4136 msa = viewport.getAlignmentView(false);
4141 msa = viewport.getAlignmentView(false);
4147 * Decides what is submitted to a secondary structure prediction service: the
4148 * first sequence in the alignment, or in the current selection, or, if the
4149 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4150 * region or the whole alignment. (where the first sequence in the set is the
4151 * one that the prediction will be for).
4153 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4155 AlignmentView seqs = null;
4157 if ((viewport.getSelectionGroup() != null)
4158 && (viewport.getSelectionGroup().getSize() > 0))
4160 seqs = viewport.getAlignmentView(true);
4164 seqs = viewport.getAlignmentView(false);
4166 // limit sequences - JBPNote in future - could spawn multiple prediction
4168 // TODO: viewport.getAlignment().isAligned is a global state - the local
4169 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4170 if (!viewport.getAlignment().isAligned(false))
4172 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4173 // TODO: if seqs.getSequences().length>1 then should really have warned
4187 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4189 // Pick the tree file
4190 JalviewFileChooser chooser = new JalviewFileChooser(
4191 Cache.getProperty("LAST_DIRECTORY"));
4192 chooser.setFileView(new JalviewFileView());
4193 chooser.setDialogTitle(
4194 MessageManager.getString("label.select_newick_like_tree_file"));
4195 chooser.setToolTipText(
4196 MessageManager.getString("label.load_tree_file"));
4198 chooser.setResponseHandler(0, () -> {
4199 String filePath = chooser.getSelectedFile().getPath();
4200 Cache.setProperty("LAST_DIRECTORY", filePath);
4201 NewickFile fin = null;
4204 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4205 DataSourceType.FILE));
4206 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4207 } catch (Exception ex)
4209 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4210 MessageManager.getString("label.problem_reading_tree_file"),
4211 JvOptionPane.WARNING_MESSAGE);
4212 ex.printStackTrace();
4214 if (fin != null && fin.hasWarningMessage())
4216 JvOptionPane.showMessageDialog(Desktop.desktop,
4217 fin.getWarningMessage(),
4219 .getString("label.possible_problem_with_tree_file"),
4220 JvOptionPane.WARNING_MESSAGE);
4223 chooser.showOpenDialog(this);
4226 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4228 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4231 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4232 int h, int x, int y)
4234 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4238 * Add a treeviewer for the tree extracted from a Newick file object to the
4239 * current alignment view
4246 * Associated alignment input data (or null)
4255 * @return TreePanel handle
4257 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4258 AlignmentView input, int w, int h, int x, int y)
4260 TreePanel tp = null;
4266 if (nf.getTree() != null)
4268 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4274 tp.setLocation(x, y);
4277 Desktop.addInternalFrame(tp, treeTitle, w, h);
4279 } catch (Exception ex)
4281 ex.printStackTrace();
4287 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4290 int w = 400, h = 500;
4294 NewickFile fin = new NewickFile(
4295 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4296 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4297 + (aa.sequenceRef != null
4298 ? (" for " + aa.sequenceRef.getDisplayId(false))
4301 showColumnWiseTree(fin, aa, title, w, h, x, y);
4302 } catch (Throwable xx)
4304 Console.error("Unexpected exception showing tree for contact matrix",
4309 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4310 String treeTitle, int w, int h, int x, int y)
4315 if (nf.getTree() == null)
4319 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4325 tp.setLocation(x, y);
4328 Desktop.addInternalFrame(tp, treeTitle, w, h);
4330 } catch (Throwable xx)
4332 Console.error("Unexpected exception showing tree for contact matrix",
4338 private boolean buildingMenu = false;
4341 * Generates menu items and listener event actions for web service clients
4344 public void BuildWebServiceMenu()
4346 while (buildingMenu)
4351 .errPrintln("Waiting for building menu to finish.");
4353 } catch (Exception e)
4357 final AlignFrame me = this;
4358 buildingMenu = true;
4359 new Thread(new Runnable()
4364 final List<JMenuItem> legacyItems = new ArrayList<>();
4367 // jalview.bin.Console.errPrintln("Building ws menu again "
4368 // + Thread.currentThread());
4369 // TODO: add support for context dependent disabling of services based
4371 // alignment and current selection
4372 // TODO: add additional serviceHandle parameter to specify abstract
4374 // class independently of AbstractName
4375 // TODO: add in rediscovery GUI function to restart discoverer
4376 // TODO: group services by location as well as function and/or
4378 // object broker mechanism.
4379 final Vector<JMenu> wsmenu = new Vector<>();
4380 final IProgressIndicator af = me;
4383 * do not i18n these strings - they are hard-coded in class
4384 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4385 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4387 final JMenu msawsmenu = new JMenu("Alignment");
4388 final JMenu secstrmenu = new JMenu(
4389 "Secondary Structure Prediction");
4390 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4391 final JMenu analymenu = new JMenu("Analysis");
4392 final JMenu dismenu = new JMenu("Protein Disorder");
4393 // JAL-940 - only show secondary structure prediction services from
4394 // the legacy server
4395 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4397 Discoverer.services != null && (Discoverer.services.size() > 0))
4399 // TODO: refactor to allow list of AbstractName/Handler bindings to
4401 // stored or retrieved from elsewhere
4402 // No MSAWS used any more:
4403 // Vector msaws = null; // (Vector)
4404 // Discoverer.services.get("MsaWS");
4405 Vector<ServiceHandle> secstrpr = Discoverer.services
4407 if (secstrpr != null)
4409 // Add any secondary structure prediction services
4410 for (int i = 0, j = secstrpr.size(); i < j; i++)
4412 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4413 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4414 .getServiceClient(sh);
4415 int p = secstrmenu.getItemCount();
4416 impl.attachWSMenuEntry(secstrmenu, me);
4417 int q = secstrmenu.getItemCount();
4418 for (int litm = p; litm < q; litm++)
4420 legacyItems.add(secstrmenu.getItem(litm));
4426 // Add all submenus in the order they should appear on the web
4428 wsmenu.add(msawsmenu);
4429 wsmenu.add(secstrmenu);
4430 wsmenu.add(dismenu);
4431 wsmenu.add(analymenu);
4432 // No search services yet
4433 // wsmenu.add(seqsrchmenu);
4435 javax.swing.SwingUtilities.invokeLater(new Runnable()
4442 webService.removeAll();
4443 // first, add discovered services onto the webservices menu
4444 if (wsmenu.size() > 0)
4446 for (int i = 0, j = wsmenu.size(); i < j; i++)
4448 webService.add(wsmenu.get(i));
4453 webService.add(me.webServiceNoServices);
4455 // TODO: move into separate menu builder class.
4457 // logic for 2.11.1.4 is
4458 // always look to see if there is a discover. if there isn't
4459 // we can't show any Jws2 services
4460 // if there are services available, show them - regardless of
4461 // the 'show JWS2 preference'
4462 // if the discoverer is running then say so
4463 // otherwise offer to trigger discovery if 'show JWS2' is not
4465 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4466 if (jws2servs != null)
4468 if (jws2servs.hasServices())
4470 jws2servs.attachWSMenuEntry(webService, me);
4471 for (Jws2Instance sv : jws2servs.getServices())
4473 if (sv.description.toLowerCase(Locale.ROOT)
4476 for (JMenuItem jmi : legacyItems)
4478 jmi.setVisible(false);
4484 if (jws2servs.isRunning())
4486 JMenuItem tm = new JMenuItem(
4487 "Still discovering JABA Services");
4488 tm.setEnabled(false);
4491 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4493 JMenuItem enableJws2 = new JMenuItem(
4494 "Discover Web Services");
4495 enableJws2.setToolTipText(
4496 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4497 enableJws2.setEnabled(true);
4498 enableJws2.addActionListener(new ActionListener()
4502 public void actionPerformed(ActionEvent e)
4504 // start service discoverer, but ignore preference
4505 Desktop.instance.startServiceDiscovery(false,
4509 webService.add(enableJws2);
4513 build_urlServiceMenu(me.webService);
4514 build_fetchdbmenu(webService);
4515 for (JMenu item : wsmenu)
4517 if (item.getItemCount() == 0)
4519 item.setEnabled(false);
4523 item.setEnabled(true);
4526 } catch (Exception e)
4529 "Exception during web service menu building process.",
4534 } catch (Exception e)
4537 buildingMenu = false;
4544 * construct any groupURL type service menu entries.
4548 protected void build_urlServiceMenu(JMenu webService)
4550 // TODO: remove this code when 2.7 is released
4551 // DEBUG - alignmentView
4553 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4554 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4556 * @Override public void actionPerformed(ActionEvent e) {
4557 * jalview.datamodel.AlignmentView
4558 * .testSelectionViews(af.viewport.getAlignment(),
4559 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4561 * }); webService.add(testAlView);
4563 // TODO: refactor to RestClient discoverer and merge menu entries for
4564 // rest-style services with other types of analysis/calculation service
4565 // SHmmr test client - still being implemented.
4566 // DEBUG - alignmentView
4568 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4571 client.attachWSMenuEntry(
4572 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4578 * Searches the alignment sequences for xRefs and builds the Show
4579 * Cross-References menu (formerly called Show Products), with database
4580 * sources for which cross-references are found (protein sources for a
4581 * nucleotide alignment and vice versa)
4583 * @return true if Show Cross-references menu should be enabled
4585 public boolean canShowProducts()
4587 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4588 AlignmentI dataset = viewport.getAlignment().getDataset();
4590 showProducts.removeAll();
4591 final boolean dna = viewport.getAlignment().isNucleotide();
4593 if (seqs == null || seqs.length == 0)
4595 // nothing to see here.
4599 boolean showp = false;
4602 List<String> ptypes = new CrossRef(seqs, dataset)
4603 .findXrefSourcesForSequences(dna);
4605 for (final String source : ptypes)
4608 final AlignFrame af = this;
4609 JMenuItem xtype = new JMenuItem(source);
4610 xtype.addActionListener(new ActionListener()
4613 public void actionPerformed(ActionEvent e)
4615 showProductsFor(af.viewport.getSequenceSelection(), dna,
4619 showProducts.add(xtype);
4621 showProducts.setVisible(showp);
4622 showProducts.setEnabled(showp);
4623 } catch (Exception e)
4626 "canShowProducts threw an exception - please report to help@jalview.org",
4634 * Finds and displays cross-references for the selected sequences (protein
4635 * products for nucleotide sequences, dna coding sequences for peptides).
4638 * the sequences to show cross-references for
4640 * true if from a nucleotide alignment (so showing proteins)
4642 * the database to show cross-references for
4644 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4645 final String source)
4647 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4652 * Construct and display a new frame containing the translation of this
4653 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4656 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4658 AlignmentI al = null;
4661 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4663 al = dna.translateCdna(codeTable);
4664 } catch (Exception ex)
4666 Console.error("Exception during translation. Please report this !",
4668 final String msg = MessageManager.getString(
4669 "label.error_when_translating_sequences_submit_bug_report");
4670 final String errorTitle = MessageManager
4671 .getString("label.implementation_error")
4672 + MessageManager.getString("label.translation_failed");
4673 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4674 JvOptionPane.ERROR_MESSAGE);
4677 if (al == null || al.getHeight() == 0)
4679 final String msg = MessageManager.getString(
4680 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4681 final String errorTitle = MessageManager
4682 .getString("label.translation_failed");
4683 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4684 JvOptionPane.WARNING_MESSAGE);
4688 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4689 af.setFileFormat(this.currentFileFormat);
4690 final String newTitle = MessageManager
4691 .formatMessage("label.translation_of_params", new Object[]
4692 { this.getTitle(), codeTable.getId() });
4693 af.setTitle(newTitle);
4694 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4696 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4697 viewport.openSplitFrame(af, new Alignment(seqs));
4701 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4708 * Set the file format
4712 public void setFileFormat(FileFormatI format)
4714 this.currentFileFormat = format;
4718 * Try to load a features file onto the alignment.
4721 * contents or path to retrieve file or a File object
4723 * access mode of file (see jalview.io.AlignFile)
4724 * @return true if features file was parsed correctly.
4726 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4729 return avc.parseFeaturesFile(file, sourceType,
4730 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4735 public void refreshFeatureUI(boolean enableIfNecessary)
4737 // note - currently this is only still here rather than in the controller
4738 // because of the featureSettings hard reference that is yet to be
4740 if (enableIfNecessary)
4742 viewport.setShowSequenceFeatures(true);
4743 showSeqFeatures.setSelected(true);
4749 public void dragEnter(DropTargetDragEvent evt)
4754 public void dragExit(DropTargetEvent evt)
4759 public void dragOver(DropTargetDragEvent evt)
4764 public void dropActionChanged(DropTargetDragEvent evt)
4769 public void drop(DropTargetDropEvent evt)
4771 // JAL-1552 - acceptDrop required before getTransferable call for
4772 // Java's Transferable for native dnd
4773 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4774 Transferable t = evt.getTransferable();
4776 final AlignFrame thisaf = this;
4777 final List<Object> files = new ArrayList<>();
4778 List<DataSourceType> protocols = new ArrayList<>();
4782 Desktop.transferFromDropTarget(files, protocols, evt, t);
4783 } catch (Exception e)
4785 e.printStackTrace();
4789 new Thread(new Runnable()
4796 // check to see if any of these files have names matching sequences
4799 SequenceIdMatcher idm = new SequenceIdMatcher(
4800 viewport.getAlignment().getSequencesArray());
4802 * Object[] { String,SequenceI}
4804 ArrayList<Object[]> filesmatched = new ArrayList<>();
4805 ArrayList<Object> filesnotmatched = new ArrayList<>();
4806 for (int i = 0; i < files.size(); i++)
4809 Object file = files.get(i);
4810 String fileName = file.toString();
4812 DataSourceType protocol = (file instanceof File
4813 ? DataSourceType.FILE
4814 : FormatAdapter.checkProtocol(fileName));
4815 if (protocol == DataSourceType.FILE)
4818 if (file instanceof File)
4821 Platform.cacheFileData(fl);
4825 fl = new File(fileName);
4827 pdbfn = fl.getName();
4829 else if (protocol == DataSourceType.URL)
4831 URL url = new URL(fileName);
4832 pdbfn = url.getFile();
4834 if (pdbfn.length() > 0)
4836 // attempt to find a match in the alignment
4837 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4838 int l = 0, c = pdbfn.indexOf(".");
4839 while (mtch == null && c != -1)
4844 } while ((c = pdbfn.indexOf(".", l)) > l);
4847 pdbfn = pdbfn.substring(0, l);
4849 mtch = idm.findAllIdMatches(pdbfn);
4856 type = new IdentifyFile().identify(file, protocol);
4857 } catch (Exception ex)
4861 if (type != null && type.isStructureFile())
4863 filesmatched.add(new Object[] { file, protocol, mtch });
4867 // File wasn't named like one of the sequences or wasn't a PDB
4869 filesnotmatched.add(file);
4873 if (filesmatched.size() > 0)
4875 boolean autoAssociate = Cache
4876 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4879 String msg = MessageManager.formatMessage(
4880 "label.automatically_associate_structure_files_with_sequences_same_name",
4882 { Integer.valueOf(filesmatched.size())
4884 String ttl = MessageManager.getString(
4885 "label.automatically_associate_structure_files_by_name");
4886 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4887 ttl, JvOptionPane.YES_NO_OPTION);
4888 autoAssociate = choice == JvOptionPane.YES_OPTION;
4892 for (Object[] fm : filesmatched)
4894 // try and associate
4895 // TODO: may want to set a standard ID naming formalism for
4896 // associating PDB files which have no IDs.
4897 for (SequenceI toassoc : (SequenceI[]) fm[2])
4899 PDBEntry pe = new AssociatePdbFileWithSeq()
4900 .associatePdbWithSeq(fm[0].toString(),
4901 (DataSourceType) fm[1], toassoc, false,
4905 jalview.bin.Console.errPrintln("Associated file : "
4906 + (fm[0].toString()) + " with "
4907 + toassoc.getDisplayId(true));
4911 // TODO: do we need to update overview ? only if features are
4913 alignPanel.paintAlignment(true, false);
4919 * add declined structures as sequences
4921 for (Object[] o : filesmatched)
4923 filesnotmatched.add(o[0]);
4927 if (filesnotmatched.size() > 0)
4929 if (assocfiles > 0 && (Cache.getDefault(
4930 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4931 || JvOptionPane.showConfirmDialog(thisaf,
4932 "<html>" + MessageManager.formatMessage(
4933 "label.ignore_unmatched_dropped_files_info",
4936 filesnotmatched.size())
4939 MessageManager.getString(
4940 "label.ignore_unmatched_dropped_files"),
4941 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4945 for (Object fn : filesnotmatched)
4947 loadJalviewDataFile(fn, null, null, null);
4951 } catch (Exception ex)
4953 ex.printStackTrace();
4961 * Attempt to load a "dropped" file or URL string, by testing in turn for
4963 * <li>an Annotation file</li>
4964 * <li>a JNet file</li>
4965 * <li>a features file</li>
4966 * <li>else try to interpret as an alignment file</li>
4970 * either a filename or a URL string.
4972 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4973 FileFormatI format, SequenceI assocSeq)
4975 // BH 2018 was String file
4978 if (sourceType == null)
4980 sourceType = FormatAdapter.checkProtocol(file);
4982 // if the file isn't identified, or not positively identified as some
4983 // other filetype (PFAM is default unidentified alignment file type) then
4984 // try to parse as annotation.
4985 boolean isAnnotation = (format == null
4986 || FileFormat.Pfam.equals(format))
4987 ? new AnnotationFile().annotateAlignmentView(viewport,
4993 // first see if its a T-COFFEE score file
4994 TCoffeeScoreFile tcf = null;
4997 tcf = new TCoffeeScoreFile(file, sourceType);
5000 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5004 new TCoffeeColourScheme(viewport.getAlignment()));
5005 isAnnotation = true;
5006 setStatus(MessageManager.getString(
5007 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5011 // some problem - if no warning its probable that the ID matching
5012 // process didn't work
5013 JvOptionPane.showMessageDialog(Desktop.desktop,
5014 tcf.getWarningMessage() == null
5015 ? MessageManager.getString(
5016 "label.check_file_matches_sequence_ids_alignment")
5017 : tcf.getWarningMessage(),
5018 MessageManager.getString(
5019 "label.problem_reading_tcoffee_score_file"),
5020 JvOptionPane.WARNING_MESSAGE);
5027 } catch (Exception x)
5030 "Exception when processing data source as T-COFFEE score file",
5036 // try to see if its a JNet 'concise' style annotation file *before*
5038 // try to parse it as a features file
5041 format = new IdentifyFile().identify(file, sourceType);
5043 if (FileFormat.ScoreMatrix == format)
5045 ScoreMatrixFile sm = new ScoreMatrixFile(
5046 new FileParse(file, sourceType));
5048 // todo: i18n this message
5049 setStatus(MessageManager.formatMessage(
5050 "label.successfully_loaded_matrix",
5051 sm.getMatrixName()));
5053 else if (FileFormat.Jnet.equals(format))
5055 JPredFile predictions = new JPredFile(file, sourceType);
5056 new JnetAnnotationMaker();
5057 JnetAnnotationMaker.add_annotation(predictions,
5058 viewport.getAlignment(), 0, false);
5059 viewport.getAlignment().setupJPredAlignment();
5060 isAnnotation = true;
5062 // else if (IdentifyFile.FeaturesFile.equals(format))
5063 else if (FileFormat.Features.equals(format))
5065 if (parseFeaturesFile(file, sourceType))
5067 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5068 if (splitFrame != null)
5070 splitFrame.repaint();
5074 alignPanel.paintAlignment(true, true);
5080 new FileLoader().LoadFile(viewport, file, sourceType, format);
5087 alignPanel.adjustAnnotationHeight();
5088 viewport.updateSequenceIdColours();
5089 buildSortByAnnotationScoresMenu();
5090 alignPanel.paintAlignment(true, true);
5092 } catch (Exception ex)
5094 ex.printStackTrace();
5095 } catch (OutOfMemoryError oom)
5100 } catch (Exception x)
5105 + (sourceType != null
5106 ? (sourceType == DataSourceType.PASTE
5108 : "using " + sourceType + " from "
5112 ? "(parsing as '" + format + "' file)"
5114 oom, Desktop.desktop);
5119 * Method invoked by the ChangeListener on the tabbed pane, in other words
5120 * when a different tabbed pane is selected by the user or programmatically.
5123 public void tabSelectionChanged(int index)
5128 * update current Overview window title (if there is one)
5129 * to add view name "Original" if necessary
5131 alignPanel.setOverviewTitle(this);
5134 * switch panels and set Overview title (if there is one
5135 * because it was opened automatically)
5137 alignPanel = alignPanels.get(index);
5138 alignPanel.setOverviewTitle(this);
5140 viewport = alignPanel.av;
5141 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5142 setMenusFromViewport(viewport);
5143 if (featureSettings != null && featureSettings.isOpen()
5144 && featureSettings.fr.getViewport() != viewport)
5146 if (viewport.isShowSequenceFeatures())
5148 // refresh the featureSettings to reflect UI change
5149 showFeatureSettingsUI();
5153 // close feature settings for this view.
5154 featureSettings.close();
5161 * 'focus' any colour slider that is open to the selected viewport
5163 if (viewport.getConservationSelected())
5165 SliderPanel.setConservationSlider(alignPanel,
5166 viewport.getResidueShading(), alignPanel.getViewName());
5170 SliderPanel.hideConservationSlider();
5172 if (viewport.getAbovePIDThreshold())
5174 SliderPanel.setPIDSliderSource(alignPanel,
5175 viewport.getResidueShading(), alignPanel.getViewName());
5179 SliderPanel.hidePIDSlider();
5183 * If there is a frame linked to this one in a SplitPane, switch it to the
5184 * same view tab index. No infinite recursion of calls should happen, since
5185 * tabSelectionChanged() should not get invoked on setting the selected
5186 * index to an unchanged value. Guard against setting an invalid index
5187 * before the new view peer tab has been created.
5189 final AlignViewportI peer = viewport.getCodingComplement();
5192 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5193 .getAlignPanel().alignFrame;
5194 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5196 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5202 * On right mouse click on view tab, prompt for and set new view name.
5205 public void tabbedPane_mousePressed(MouseEvent e)
5207 if (e.isPopupTrigger())
5209 String msg = MessageManager.getString("label.enter_view_name");
5210 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5211 String reply = JvOptionPane.showInputDialog(msg, ttl);
5215 viewport.setViewName(reply);
5216 // TODO warn if reply is in getExistingViewNames()?
5217 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5222 public AlignViewport getCurrentView()
5228 * Open the dialog for regex description parsing.
5231 protected void extractScores_actionPerformed(ActionEvent e)
5233 ParseProperties pp = new jalview.analysis.ParseProperties(
5234 viewport.getAlignment());
5235 // TODO: verify regex and introduce GUI dialog for version 2.5
5236 // if (pp.getScoresFromDescription("col", "score column ",
5237 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5239 if (pp.getScoresFromDescription("description column",
5240 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5242 buildSortByAnnotationScoresMenu();
5250 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5254 protected void showDbRefs_actionPerformed(ActionEvent e)
5256 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5262 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5266 protected void showNpFeats_actionPerformed(ActionEvent e)
5268 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5272 * find the viewport amongst the tabs in this alignment frame and close that
5277 public boolean closeView(AlignViewportI av)
5281 this.closeMenuItem_actionPerformed(false);
5284 Component[] comp = tabbedPane.getComponents();
5285 for (int i = 0; comp != null && i < comp.length; i++)
5287 if (comp[i] instanceof AlignmentPanel)
5289 if (((AlignmentPanel) comp[i]).av == av)
5292 closeView((AlignmentPanel) comp[i]);
5300 protected void build_fetchdbmenu(JMenu webService)
5302 // Temporary hack - DBRef Fetcher always top level ws entry.
5303 // TODO We probably want to store a sequence database checklist in
5304 // preferences and have checkboxes.. rather than individual sources selected
5306 final JMenu rfetch = new JMenu(
5307 MessageManager.getString("action.fetch_db_references"));
5308 rfetch.setToolTipText(MessageManager.getString(
5309 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5310 webService.add(rfetch);
5312 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5313 MessageManager.getString("option.trim_retrieved_seqs"));
5314 trimrs.setToolTipText(
5315 MessageManager.getString("label.trim_retrieved_sequences"));
5317 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5318 trimrs.addActionListener(new ActionListener()
5321 public void actionPerformed(ActionEvent e)
5323 trimrs.setSelected(trimrs.isSelected());
5324 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5325 Boolean.valueOf(trimrs.isSelected()).toString());
5329 JMenuItem fetchr = new JMenuItem(
5330 MessageManager.getString("label.standard_databases"));
5331 fetchr.setToolTipText(
5332 MessageManager.getString("label.fetch_embl_uniprot"));
5333 fetchr.addActionListener(new ActionListener()
5337 public void actionPerformed(ActionEvent e)
5339 new Thread(new Runnable()
5344 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5345 .getAlignment().isNucleotide();
5346 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5347 alignPanel.av.getSequenceSelection(),
5348 alignPanel.alignFrame, null,
5349 alignPanel.alignFrame.featureSettings, isNucleotide);
5350 dbRefFetcher.addListener(new FetchFinishedListenerI()
5353 public void finished()
5356 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5357 .getFeatureSettingsModels())
5360 alignPanel.av.mergeFeaturesStyle(srcSettings);
5362 AlignFrame.this.setMenusForViewport();
5365 dbRefFetcher.fetchDBRefs(false);
5373 new Thread(new Runnable()
5378 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5379 .getSequenceFetcherSingleton();
5380 javax.swing.SwingUtilities.invokeLater(new Runnable()
5385 String[] dbclasses = sf.getNonAlignmentSources();
5386 List<DbSourceProxy> otherdb;
5387 JMenu dfetch = new JMenu();
5388 JMenu ifetch = new JMenu();
5389 JMenuItem fetchr = null;
5390 int comp = 0, icomp = 0, mcomp = 15;
5391 String mname = null;
5393 for (String dbclass : dbclasses)
5395 otherdb = sf.getSourceProxy(dbclass);
5396 // add a single entry for this class, or submenu allowing 'fetch
5398 if (otherdb == null || otherdb.size() < 1)
5404 mname = "From " + dbclass;
5406 if (otherdb.size() == 1)
5408 final DbSourceProxy[] dassource = otherdb
5409 .toArray(new DbSourceProxy[0]);
5410 DbSourceProxy src = otherdb.get(0);
5411 fetchr = new JMenuItem(src.getDbSource());
5412 fetchr.addActionListener(new ActionListener()
5416 public void actionPerformed(ActionEvent e)
5418 new Thread(new Runnable()
5424 boolean isNucleotide = alignPanel.alignFrame
5425 .getViewport().getAlignment()
5427 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5428 alignPanel.av.getSequenceSelection(),
5429 alignPanel.alignFrame, dassource,
5430 alignPanel.alignFrame.featureSettings,
5433 .addListener(new FetchFinishedListenerI()
5436 public void finished()
5438 FeatureSettingsModelI srcSettings = dassource[0]
5439 .getFeatureColourScheme();
5440 alignPanel.av.mergeFeaturesStyle(
5442 AlignFrame.this.setMenusForViewport();
5445 dbRefFetcher.fetchDBRefs(false);
5451 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5452 MessageManager.formatMessage(
5453 "label.fetch_retrieve_from", new Object[]
5454 { src.getDbName() })));
5460 final DbSourceProxy[] dassource = otherdb
5461 .toArray(new DbSourceProxy[0]);
5463 DbSourceProxy src = otherdb.get(0);
5464 fetchr = new JMenuItem(MessageManager
5465 .formatMessage("label.fetch_all_param", new Object[]
5466 { src.getDbSource() }));
5467 fetchr.addActionListener(new ActionListener()
5470 public void actionPerformed(ActionEvent e)
5472 new Thread(new Runnable()
5478 boolean isNucleotide = alignPanel.alignFrame
5479 .getViewport().getAlignment()
5481 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5482 alignPanel.av.getSequenceSelection(),
5483 alignPanel.alignFrame, dassource,
5484 alignPanel.alignFrame.featureSettings,
5487 .addListener(new FetchFinishedListenerI()
5490 public void finished()
5492 AlignFrame.this.setMenusForViewport();
5495 dbRefFetcher.fetchDBRefs(false);
5501 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5502 MessageManager.formatMessage(
5503 "label.fetch_retrieve_from_all_sources",
5505 { Integer.valueOf(otherdb.size())
5507 src.getDbSource(), src.getDbName() })));
5510 // and then build the rest of the individual menus
5511 ifetch = new JMenu(MessageManager.formatMessage(
5512 "label.source_from_db_source", new Object[]
5513 { src.getDbSource() }));
5515 String imname = null;
5517 for (DbSourceProxy sproxy : otherdb)
5519 String dbname = sproxy.getDbName();
5520 String sname = dbname.length() > 5
5521 ? dbname.substring(0, 5) + "..."
5523 String msname = dbname.length() > 10
5524 ? dbname.substring(0, 10) + "..."
5528 imname = MessageManager
5529 .formatMessage("label.from_msname", new Object[]
5532 fetchr = new JMenuItem(msname);
5533 final DbSourceProxy[] dassrc = { sproxy };
5534 fetchr.addActionListener(new ActionListener()
5538 public void actionPerformed(ActionEvent e)
5540 new Thread(new Runnable()
5546 boolean isNucleotide = alignPanel.alignFrame
5547 .getViewport().getAlignment()
5549 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5550 alignPanel.av.getSequenceSelection(),
5551 alignPanel.alignFrame, dassrc,
5552 alignPanel.alignFrame.featureSettings,
5555 .addListener(new FetchFinishedListenerI()
5558 public void finished()
5560 AlignFrame.this.setMenusForViewport();
5563 dbRefFetcher.fetchDBRefs(false);
5569 fetchr.setToolTipText(
5570 "<html>" + MessageManager.formatMessage(
5571 "label.fetch_retrieve_from", new Object[]
5575 if (++icomp >= mcomp || i == (otherdb.size()))
5577 ifetch.setText(MessageManager.formatMessage(
5578 "label.source_to_target", imname, sname));
5580 ifetch = new JMenu();
5588 if (comp >= mcomp || dbi >= (dbclasses.length))
5590 dfetch.setText(MessageManager.formatMessage(
5591 "label.source_to_target", mname, dbclass));
5593 dfetch = new JMenu();
5606 * Left justify the whole alignment.
5609 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5611 AlignmentI al = viewport.getAlignment();
5613 viewport.firePropertyChange("alignment", null, al);
5617 * Right justify the whole alignment.
5620 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5622 AlignmentI al = viewport.getAlignment();
5624 viewport.firePropertyChange("alignment", null, al);
5628 public void setShowSeqFeatures(boolean b)
5630 showSeqFeatures.setSelected(b);
5631 viewport.setShowSequenceFeatures(b);
5638 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5639 * awt.event.ActionEvent)
5642 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5644 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5645 alignPanel.paintAlignment(false, false);
5652 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5656 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5658 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5659 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5667 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5668 * .event.ActionEvent)
5671 protected void showGroupConservation_actionPerformed(ActionEvent e)
5673 viewport.setShowGroupConservation(showGroupConservation.getState());
5674 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5681 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5682 * .event.ActionEvent)
5685 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5687 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5688 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5695 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5696 * .event.ActionEvent)
5699 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5701 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5702 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5706 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5708 showSequenceLogo.setState(true);
5709 viewport.setShowSequenceLogo(true);
5710 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5711 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5715 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5717 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5724 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5725 * .event.ActionEvent)
5728 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5730 if (avc.makeGroupsFromSelection())
5732 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5733 alignPanel.updateAnnotation();
5734 alignPanel.paintAlignment(true,
5735 viewport.needToUpdateStructureViews());
5739 public void clearAlignmentSeqRep()
5741 // TODO refactor alignmentseqrep to controller
5742 if (viewport.getAlignment().hasSeqrep())
5744 viewport.getAlignment().setSeqrep(null);
5745 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5746 alignPanel.updateAnnotation();
5747 alignPanel.paintAlignment(true, true);
5752 protected void createGroup_actionPerformed(ActionEvent e)
5754 if (avc.createGroup())
5756 if (applyAutoAnnotationSettings.isSelected())
5758 alignPanel.updateAnnotation(true, false);
5760 alignPanel.alignmentChanged();
5765 protected void unGroup_actionPerformed(ActionEvent e)
5769 alignPanel.alignmentChanged();
5774 * make the given alignmentPanel the currently selected tab
5776 * @param alignmentPanel
5778 public void setDisplayedView(AlignmentPanel alignmentPanel)
5780 if (!viewport.getSequenceSetId()
5781 .equals(alignmentPanel.av.getSequenceSetId()))
5783 throw new Error(MessageManager.getString(
5784 "error.implementation_error_cannot_show_view_alignment_frame"));
5786 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5787 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5789 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5794 * Action on selection of menu options to Show or Hide annotations.
5797 * @param forSequences
5798 * update sequence-related annotations
5799 * @param forAlignment
5800 * update non-sequence-related annotations
5803 public void setAnnotationsVisibility(boolean visible,
5804 boolean forSequences, boolean forAlignment)
5806 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5807 .getAlignmentAnnotation();
5812 for (AlignmentAnnotation aa : anns)
5815 * don't display non-positional annotations on an alignment
5817 if (aa.annotations == null)
5821 boolean apply = (aa.sequenceRef == null && forAlignment)
5822 || (aa.sequenceRef != null && forSequences);
5825 aa.visible = visible;
5828 alignPanel.validateAnnotationDimensions(true);
5829 alignPanel.alignmentChanged();
5833 * Store selected annotation sort order for the view and repaint.
5836 protected void sortAnnotations_actionPerformed()
5838 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5840 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5841 alignPanel.paintAlignment(false, false);
5846 * @return alignment panels in this alignment frame
5848 public List<? extends AlignmentViewPanel> getAlignPanels()
5850 // alignPanels is never null
5851 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5856 * Open a new alignment window, with the cDNA associated with this (protein)
5857 * alignment, aligned as is the protein.
5859 protected void viewAsCdna_actionPerformed()
5861 // TODO no longer a menu action - refactor as required
5862 final AlignmentI alignment = getViewport().getAlignment();
5863 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5864 if (mappings == null)
5868 List<SequenceI> cdnaSeqs = new ArrayList<>();
5869 for (SequenceI aaSeq : alignment.getSequences())
5871 for (AlignedCodonFrame acf : mappings)
5873 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5877 * There is a cDNA mapping for this protein sequence - add to new
5878 * alignment. It will share the same dataset sequence as other mapped
5879 * cDNA (no new mappings need to be created).
5881 final Sequence newSeq = new Sequence(dnaSeq);
5882 newSeq.setDatasetSequence(dnaSeq);
5883 cdnaSeqs.add(newSeq);
5887 if (cdnaSeqs.size() == 0)
5889 // show a warning dialog no mapped cDNA
5892 AlignmentI cdna = new Alignment(
5893 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5894 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5895 AlignFrame.DEFAULT_HEIGHT);
5896 cdna.alignAs(alignment);
5897 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5899 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5900 AlignFrame.DEFAULT_HEIGHT);
5904 * Set visibility of dna/protein complement view (available when shown in a
5910 protected void showComplement_actionPerformed(boolean show)
5912 SplitContainerI sf = getSplitViewContainer();
5915 sf.setComplementVisible(this, show);
5920 * Generate the reverse (optionally complemented) of the selected sequences,
5921 * and add them to the alignment
5924 protected void showReverse_actionPerformed(boolean complement)
5926 AlignmentI al = null;
5929 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5930 al = dna.reverseCdna(complement);
5931 viewport.addAlignment(al, "");
5932 addHistoryItem(new EditCommand(
5933 MessageManager.getString("label.add_sequences"), Action.PASTE,
5934 al.getSequencesArray(), 0, al.getWidth(),
5935 viewport.getAlignment()));
5936 } catch (Exception ex)
5938 jalview.bin.Console.errPrintln(ex.getMessage());
5944 * Try to run a script in the Groovy console, having first ensured that this
5945 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5946 * be targeted at this alignment.
5949 protected void runGroovy_actionPerformed()
5951 Jalview.setCurrentAlignFrame(this);
5952 groovy.ui.Console console = Desktop.getGroovyConsole();
5953 if (console != null)
5957 console.runScript();
5958 } catch (Exception ex)
5960 jalview.bin.Console.errPrintln((ex.toString()));
5961 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5962 MessageManager.getString("label.couldnt_run_groovy_script"),
5963 MessageManager.getString("label.groovy_support_failed"),
5964 JvOptionPane.ERROR_MESSAGE);
5970 .errPrintln("Can't run Groovy script as console not found");
5975 * Hides columns containing (or not containing) a specified feature, provided
5976 * that would not leave all columns hidden
5978 * @param featureType
5979 * @param columnsContaining
5982 public boolean hideFeatureColumns(String featureType,
5983 boolean columnsContaining)
5985 boolean notForHiding = avc.markColumnsContainingFeatures(
5986 columnsContaining, false, false, featureType);
5989 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5990 false, featureType))
5992 getViewport().hideSelectedColumns();
6000 protected void selectHighlightedColumns_actionPerformed(
6001 ActionEvent actionEvent)
6003 // include key modifier check in case user selects from menu
6004 avc.markHighlightedColumns(
6005 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6006 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6007 | ActionEvent.CTRL_MASK)) != 0);
6011 protected void copyHighlightedColumns_actionPerformed(
6012 ActionEvent actionEvent)
6014 avc.copyHighlightedRegionsToClipboard();
6018 * Rebuilds the Colour menu, including any user-defined colours which have
6019 * been loaded either on startup or during the session
6021 public void buildColourMenu()
6023 colourMenu.removeAll();
6025 colourMenu.add(applyToAllGroups);
6026 colourMenu.add(textColour);
6027 colourMenu.addSeparator();
6029 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6030 viewport.getAlignment(), false);
6032 colourMenu.add(annotationColour);
6033 bg.add(annotationColour);
6034 colourMenu.addSeparator();
6035 colourMenu.add(conservationMenuItem);
6036 colourMenu.add(modifyConservation);
6037 colourMenu.add(abovePIDThreshold);
6038 colourMenu.add(modifyPID);
6040 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6041 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6045 * Open a dialog (if not already open) that allows the user to select and
6046 * calculate PCA or Tree analysis
6048 protected void openTreePcaDialog()
6050 if (alignPanel.getCalculationDialog() == null)
6052 new CalculationChooser(AlignFrame.this);
6057 protected void loadVcf_actionPerformed()
6059 JalviewFileChooser chooser = new JalviewFileChooser(
6060 Cache.getProperty("LAST_DIRECTORY"));
6061 chooser.setFileView(new JalviewFileView());
6062 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6063 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6064 final AlignFrame us = this;
6065 chooser.setResponseHandler(0, () -> {
6066 String choice = chooser.getSelectedFile().getPath();
6067 Cache.setProperty("LAST_DIRECTORY", choice);
6068 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6069 new VCFLoader(choice).loadVCF(seqs, us);
6071 chooser.showOpenDialog(null);
6075 private Rectangle lastFeatureSettingsBounds = null;
6078 public void setFeatureSettingsGeometry(Rectangle bounds)
6080 lastFeatureSettingsBounds = bounds;
6084 public Rectangle getFeatureSettingsGeometry()
6086 return lastFeatureSettingsBounds;
6091 class PrintThread extends Thread
6095 public PrintThread(AlignmentPanel ap)
6100 static PageFormat pf;
6105 PrinterJob printJob = PrinterJob.getPrinterJob();
6109 printJob.setPrintable(ap, pf);
6113 printJob.setPrintable(ap);
6116 if (printJob.printDialog())
6121 } catch (Exception PrintException)
6123 PrintException.printStackTrace();