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.bin.groovy.JalviewObjectI;
99 import jalview.commands.CommandI;
100 import jalview.commands.EditCommand;
101 import jalview.commands.EditCommand.Action;
102 import jalview.commands.OrderCommand;
103 import jalview.commands.RemoveGapColCommand;
104 import jalview.commands.RemoveGapsCommand;
105 import jalview.commands.SlideSequencesCommand;
106 import jalview.commands.TrimRegionCommand;
107 import jalview.datamodel.AlignExportSettingsAdapter;
108 import jalview.datamodel.AlignedCodonFrame;
109 import jalview.datamodel.Alignment;
110 import jalview.datamodel.AlignmentAnnotation;
111 import jalview.datamodel.AlignmentExportData;
112 import jalview.datamodel.AlignmentI;
113 import jalview.datamodel.AlignmentOrder;
114 import jalview.datamodel.AlignmentView;
115 import jalview.datamodel.ColumnSelection;
116 import jalview.datamodel.ContactMatrixI;
117 import jalview.datamodel.HiddenColumns;
118 import jalview.datamodel.PDBEntry;
119 import jalview.datamodel.SeqCigar;
120 import jalview.datamodel.Sequence;
121 import jalview.datamodel.SequenceGroup;
122 import jalview.datamodel.SequenceI;
123 import jalview.gui.ColourMenuHelper.ColourChangeListener;
124 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
125 import jalview.io.AlignmentProperties;
126 import jalview.io.AnnotationFile;
127 import jalview.io.BackupFiles;
128 import jalview.io.BioJsHTMLOutput;
129 import jalview.io.DataSourceType;
130 import jalview.io.FileFormat;
131 import jalview.io.FileFormatI;
132 import jalview.io.FileFormats;
133 import jalview.io.FileLoader;
134 import jalview.io.FileParse;
135 import jalview.io.FormatAdapter;
136 import jalview.io.HtmlSvgOutput;
137 import jalview.io.IdentifyFile;
138 import jalview.io.JPredFile;
139 import jalview.io.JalviewFileChooser;
140 import jalview.io.JalviewFileView;
141 import jalview.io.JnetAnnotationMaker;
142 import jalview.io.NewickFile;
143 import jalview.io.ScoreMatrixFile;
144 import jalview.io.TCoffeeScoreFile;
145 import jalview.io.exceptions.ImageOutputException;
146 import jalview.io.vcf.VCFLoader;
147 import jalview.jbgui.GAlignFrame;
148 import jalview.project.Jalview2XML;
149 import jalview.schemes.ColourSchemeI;
150 import jalview.schemes.ColourSchemes;
151 import jalview.schemes.ResidueColourScheme;
152 import jalview.schemes.TCoffeeColourScheme;
153 import jalview.util.HttpUtils;
154 import jalview.util.ImageMaker.TYPE;
155 import jalview.util.MessageManager;
156 import jalview.util.Platform;
157 import jalview.util.imagemaker.BitmapImageSizing;
158 import jalview.viewmodel.AlignmentViewport;
159 import jalview.viewmodel.ViewportRanges;
160 import jalview.ws.DBRefFetcher;
161 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
162 import jalview.ws.jws1.Discoverer;
163 import jalview.ws.jws2.Jws2Discoverer;
164 import jalview.ws.jws2.jabaws2.Jws2Instance;
165 import jalview.ws.seqfetcher.DbSourceProxy;
171 * @version $Revision$
173 @SuppressWarnings("serial")
174 public class AlignFrame extends GAlignFrame implements DropTargetListener,
175 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
178 public static final int DEFAULT_WIDTH = 700;
180 public static final int DEFAULT_HEIGHT = 500;
183 * The currently displayed panel (selected tabbed view if more than one)
185 public AlignmentPanel alignPanel;
187 AlignViewport viewport;
189 public AlignViewControllerI avc;
191 List<AlignmentPanel> alignPanels = new ArrayList<>();
194 * Last format used to load or save alignments in this window
196 FileFormatI currentFileFormat = null;
199 * Current filename for this alignment
201 String fileName = null;
206 * Creates a new AlignFrame object with specific width and height.
212 public AlignFrame(AlignmentI al, int width, int height)
214 this(al, null, width, height);
218 * Creates a new AlignFrame object with specific width, height and
224 * @param sequenceSetId
226 public AlignFrame(AlignmentI al, int width, int height,
227 String sequenceSetId)
229 this(al, null, width, height, sequenceSetId);
233 * Creates a new AlignFrame object with specific width, height and
239 * @param sequenceSetId
242 public AlignFrame(AlignmentI al, int width, int height,
243 String sequenceSetId, String viewId)
245 this(al, null, width, height, sequenceSetId, viewId);
249 * new alignment window with hidden columns
253 * @param hiddenColumns
254 * ColumnSelection or null
256 * Width of alignment frame
260 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
263 this(al, hiddenColumns, width, height, null);
267 * Create alignment frame for al with hiddenColumns, a specific width and
268 * height, and specific sequenceId
271 * @param hiddenColumns
274 * @param sequenceSetId
277 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
278 int height, String sequenceSetId)
280 this(al, hiddenColumns, width, height, sequenceSetId, null);
284 * Create alignment frame for al with hiddenColumns, a specific width and
285 * height, and specific sequenceId
288 * @param hiddenColumns
291 * @param sequenceSetId
296 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
297 int height, String sequenceSetId, String viewId)
299 setSize(width, height);
301 if (al.getDataset() == null)
306 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
308 alignPanel = new AlignmentPanel(this, viewport);
310 addAlignmentPanel(alignPanel, true);
314 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
315 HiddenColumns hiddenColumns, int width, int height)
317 setSize(width, height);
319 if (al.getDataset() == null)
324 viewport = new AlignViewport(al, hiddenColumns);
326 if (hiddenSeqs != null && hiddenSeqs.length > 0)
328 viewport.hideSequence(hiddenSeqs);
330 alignPanel = new AlignmentPanel(this, viewport);
331 addAlignmentPanel(alignPanel, true);
336 * Make a new AlignFrame from existing alignmentPanels
343 public AlignFrame(AlignmentPanel ap)
347 addAlignmentPanel(ap, false);
352 * initalise the alignframe from the underlying viewport data and the
359 // setBackground(Color.white); // BH 2019
361 if (!Jalview.isHeadlessMode())
363 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
366 avc = new jalview.controller.AlignViewController(this, viewport,
368 if (viewport.getAlignmentConservationAnnotation() == null)
370 // BLOSUM62Colour.setEnabled(false);
371 conservationMenuItem.setEnabled(false);
372 modifyConservation.setEnabled(false);
373 // PIDColour.setEnabled(false);
374 // abovePIDThreshold.setEnabled(false);
375 // modifyPID.setEnabled(false);
378 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
380 if (sortby.equals("Id"))
382 sortIDMenuItem_actionPerformed(null);
384 else if (sortby.equals("Pairwise Identity"))
386 sortPairwiseMenuItem_actionPerformed(null);
390 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
392 setMenusFromViewport(viewport);
393 buildSortByAnnotationScoresMenu();
394 calculateTree.addActionListener(new ActionListener()
398 public void actionPerformed(ActionEvent e)
405 if (Desktop.desktop != null)
407 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
408 if (!Platform.isJS())
410 addServiceListeners();
415 if (viewport.getWrapAlignment())
417 wrapMenuItem_actionPerformed(null);
420 if (Cache.getDefault("SHOW_OVERVIEW", false))
422 this.overviewMenuItem_actionPerformed(null);
427 final List<AlignmentViewPanel> selviews = new ArrayList<>();
428 final List<AlignmentPanel> origview = new ArrayList<>();
429 final String menuLabel = MessageManager
430 .getString("label.copy_format_from");
431 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
432 new ViewSetProvider()
436 public AlignmentPanel[] getAllAlignmentPanels()
439 origview.add(alignPanel);
440 // make an array of all alignment panels except for this one
441 List<AlignmentPanel> aps = new ArrayList<>(
442 Arrays.asList(Desktop.getAlignmentPanels(null)));
443 aps.remove(AlignFrame.this.alignPanel);
444 return aps.toArray(new AlignmentPanel[aps.size()]);
446 }, selviews, new ItemListener()
450 public void itemStateChanged(ItemEvent e)
452 if (origview.size() > 0)
454 final AlignmentPanel ap = origview.get(0);
457 * Copy the ViewStyle of the selected panel to 'this one'.
458 * Don't change value of 'scaleProteinAsCdna' unless copying
461 ViewStyleI vs = selviews.get(0).getAlignViewport()
463 boolean fromSplitFrame = selviews.get(0)
464 .getAlignViewport().getCodingComplement() != null;
467 vs.setScaleProteinAsCdna(ap.getAlignViewport()
468 .getViewStyle().isScaleProteinAsCdna());
470 ap.getAlignViewport().setViewStyle(vs);
473 * Also rescale ViewStyle of SplitFrame complement if there is
474 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
475 * the whole ViewStyle (allow cDNA protein to have different
478 AlignViewportI complement = ap.getAlignViewport()
479 .getCodingComplement();
480 if (complement != null && vs.isScaleProteinAsCdna())
482 AlignFrame af = Desktop.getAlignFrameFor(complement);
483 ((SplitFrame) af.getSplitViewContainer())
485 af.setMenusForViewport();
489 ap.setSelected(true);
490 ap.alignFrame.setMenusForViewport();
495 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
496 .indexOf("devel") > -1
497 || Cache.getDefault("VERSION", "DEVELOPMENT")
498 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
500 formatMenu.add(vsel);
502 addFocusListener(new FocusAdapter()
505 public void focusGained(FocusEvent e)
507 Jalview.getInstance().setCurrentAlignFrame(AlignFrame.this);
514 * Change the filename and format for the alignment, and enable the 'reload'
515 * button functionality.
522 public void setFileName(String file, FileFormatI format)
525 setFileFormat(format);
526 reload.setEnabled(true);
530 * JavaScript will have this, maybe others. More dependable than a file name
531 * and maintains a reference to the actual bytes loaded.
535 public void setFileObject(File file)
537 this.fileObject = file;
541 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
544 void addKeyListener()
546 addKeyListener(new KeyAdapter()
549 public void keyPressed(KeyEvent evt)
551 if (viewport.cursorMode
552 && ((evt.getKeyCode() >= KeyEvent.VK_0
553 && evt.getKeyCode() <= KeyEvent.VK_9)
554 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
555 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
556 && Character.isDigit(evt.getKeyChar()))
558 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
561 switch (evt.getKeyCode())
564 case 27: // escape key
565 deselectAllSequenceMenuItem_actionPerformed(null);
569 case KeyEvent.VK_DOWN:
570 if (evt.isAltDown() || !viewport.cursorMode)
572 moveSelectedSequences(false);
574 if (viewport.cursorMode)
576 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
581 if (evt.isAltDown() || !viewport.cursorMode)
583 moveSelectedSequences(true);
585 if (viewport.cursorMode)
587 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
592 case KeyEvent.VK_LEFT:
593 if (evt.isAltDown() || !viewport.cursorMode)
595 slideSequences(false,
596 alignPanel.getSeqPanel().getKeyboardNo1());
600 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
605 case KeyEvent.VK_RIGHT:
606 if (evt.isAltDown() || !viewport.cursorMode)
608 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
612 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
616 case KeyEvent.VK_SPACE:
617 if (viewport.cursorMode)
619 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
620 || evt.isShiftDown() || evt.isAltDown());
624 // case KeyEvent.VK_A:
625 // if (viewport.cursorMode)
627 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
628 // //jalview.bin.Console.outPrintln("A");
632 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
633 * jalview.bin.Console.outPrintln("closing bracket"); } break;
635 case KeyEvent.VK_DELETE:
636 case KeyEvent.VK_BACK_SPACE:
637 if (!viewport.cursorMode)
639 cut_actionPerformed();
643 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
644 || evt.isShiftDown() || evt.isAltDown());
650 if (viewport.cursorMode)
652 alignPanel.getSeqPanel().setCursorRow();
656 if (viewport.cursorMode && !evt.isControlDown())
658 alignPanel.getSeqPanel().setCursorColumn();
662 if (viewport.cursorMode)
664 alignPanel.getSeqPanel().setCursorPosition();
668 case KeyEvent.VK_ENTER:
669 case KeyEvent.VK_COMMA:
670 if (viewport.cursorMode)
672 alignPanel.getSeqPanel().setCursorRowAndColumn();
677 if (viewport.cursorMode)
679 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
683 if (viewport.cursorMode)
685 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
690 viewport.cursorMode = !viewport.cursorMode;
691 setStatus(MessageManager
692 .formatMessage("label.keyboard_editing_mode", new String[]
693 { (viewport.cursorMode ? "on" : "off") }));
694 if (viewport.cursorMode)
696 ViewportRanges ranges = viewport.getRanges();
697 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
699 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
702 alignPanel.getSeqPanel().seqCanvas.repaint();
708 Help.showHelpWindow();
709 } catch (Exception ex)
711 ex.printStackTrace();
716 boolean toggleSeqs = !evt.isControlDown();
717 boolean toggleCols = !evt.isShiftDown();
718 toggleHiddenRegions(toggleSeqs, toggleCols);
723 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
724 boolean modifyExisting = true; // always modify, don't clear
725 // evt.isShiftDown();
726 boolean invertHighlighted = evt.isAltDown();
727 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
731 case KeyEvent.VK_PAGE_UP:
732 viewport.getRanges().pageUp();
734 case KeyEvent.VK_PAGE_DOWN:
735 viewport.getRanges().pageDown();
741 public void keyReleased(KeyEvent evt)
743 switch (evt.getKeyCode())
745 case KeyEvent.VK_LEFT:
746 if (evt.isAltDown() || !viewport.cursorMode)
748 viewport.firePropertyChange("alignment", null,
749 viewport.getAlignment().getSequences());
753 case KeyEvent.VK_RIGHT:
754 if (evt.isAltDown() || !viewport.cursorMode)
756 viewport.firePropertyChange("alignment", null,
757 viewport.getAlignment().getSequences());
765 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
767 ap.alignFrame = this;
768 avc = new jalview.controller.AlignViewController(this, viewport,
773 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
775 int aSize = alignPanels.size();
777 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
779 if (aSize == 1 && ap.av.getViewName() == null)
781 this.getContentPane().add(ap, BorderLayout.CENTER);
787 setInitialTabVisible();
790 expandViews.setEnabled(true);
791 gatherViews.setEnabled(true);
792 tabbedPane.addTab(ap.av.getViewName(), ap);
794 ap.setVisible(false);
799 if (ap.av.isPadGaps())
801 ap.av.getAlignment().padGaps();
803 ap.av.updateConservation(ap);
804 ap.av.updateConsensus(ap);
805 ap.av.updateStrucConsensus(ap);
809 public void setInitialTabVisible()
811 expandViews.setEnabled(true);
812 gatherViews.setEnabled(true);
813 tabbedPane.setVisible(true);
814 AlignmentPanel first = alignPanels.get(0);
815 tabbedPane.addTab(first.av.getViewName(), first);
816 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
819 public AlignViewport getViewport()
824 /* Set up intrinsic listeners for dynamically generated GUI bits. */
825 private void addServiceListeners()
827 final java.beans.PropertyChangeListener thisListener;
828 Desktop.instance.addJalviewPropertyChangeListener("services",
829 thisListener = new java.beans.PropertyChangeListener()
832 public void propertyChange(PropertyChangeEvent evt)
834 // // jalview.bin.Console.outPrintln("Discoverer property
836 // if (evt.getPropertyName().equals("services"))
838 SwingUtilities.invokeLater(new Runnable()
844 jalview.bin.Console.errPrintln(
845 "Rebuild WS Menu for service change");
846 BuildWebServiceMenu();
853 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
856 public void internalFrameClosed(
857 javax.swing.event.InternalFrameEvent evt)
859 // jalview.bin.Console.outPrintln("deregistering discoverer listener");
860 Desktop.instance.removeJalviewPropertyChangeListener("services",
862 closeMenuItem_actionPerformed(true);
865 // Finally, build the menu once to get current service state
866 new Thread(new Runnable()
871 BuildWebServiceMenu();
877 * Configure menu items that vary according to whether the alignment is
878 * nucleotide or protein
880 public void setGUINucleotide()
882 AlignmentI al = getViewport().getAlignment();
883 boolean nucleotide = al.isNucleotide();
885 loadVcf.setVisible(nucleotide);
886 showTranslation.setVisible(nucleotide);
887 showReverse.setVisible(nucleotide);
888 showReverseComplement.setVisible(nucleotide);
889 conservationMenuItem.setEnabled(!nucleotide);
891 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
892 showGroupConservation.setEnabled(!nucleotide);
894 showComplementMenuItem
895 .setText(nucleotide ? MessageManager.getString("label.protein")
896 : MessageManager.getString("label.nucleotide"));
900 * set up menus for the current viewport. This may be called after any
901 * operation that affects the data in the current view (selection changed,
902 * etc) to update the menus to reflect the new state.
905 public void setMenusForViewport()
907 setMenusFromViewport(viewport);
911 * Need to call this method when tabs are selected for multiple views, or when
912 * loading from Jalview2XML.java
917 public void setMenusFromViewport(AlignViewport av)
919 padGapsMenuitem.setSelected(av.isPadGaps());
920 colourTextMenuItem.setSelected(av.isShowColourText());
921 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
922 modifyPID.setEnabled(abovePIDThreshold.isSelected());
923 conservationMenuItem.setSelected(av.getConservationSelected());
924 modifyConservation.setEnabled(conservationMenuItem.isSelected());
925 seqLimits.setSelected(av.getShowJVSuffix());
926 idRightAlign.setSelected(av.isRightAlignIds());
927 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
928 renderGapsMenuItem.setSelected(av.isRenderGaps());
929 wrapMenuItem.setSelected(av.getWrapAlignment());
930 scaleAbove.setVisible(av.getWrapAlignment());
931 scaleLeft.setVisible(av.getWrapAlignment());
932 scaleRight.setVisible(av.getWrapAlignment());
933 annotationPanelMenuItem.setState(av.isShowAnnotation());
935 * Show/hide annotations only enabled if annotation panel is shown
937 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
938 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
939 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
940 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
941 viewBoxesMenuItem.setSelected(av.getShowBoxes());
942 viewTextMenuItem.setSelected(av.getShowText());
943 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
944 showGroupConsensus.setSelected(av.isShowGroupConsensus());
945 showGroupConservation.setSelected(av.isShowGroupConservation());
946 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
947 showSequenceLogo.setSelected(av.isShowSequenceLogo());
948 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
950 ColourMenuHelper.setColourSelected(colourMenu,
951 av.getGlobalColourScheme());
953 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
954 hiddenMarkers.setState(av.getShowHiddenMarkers());
955 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
956 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
957 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
958 autoCalculate.setSelected(av.autoCalculateConsensus);
959 sortByTree.setSelected(av.sortByTree);
960 listenToViewSelections.setSelected(av.followSelection);
962 showProducts.setEnabled(canShowProducts());
963 setGroovyEnabled(Desktop.getGroovyConsole() != null);
969 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
973 public void setGroovyEnabled(boolean b)
975 runGroovy.setEnabled(b);
978 private IProgressIndicator progressBar;
983 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
986 public void setProgressBar(String message, long id)
988 if (!Platform.isHeadless() && progressBar != null)
989 progressBar.setProgressBar(message, id);
993 public void registerHandler(final long id,
994 final IProgressIndicatorHandler handler)
996 if (progressBar != null)
997 progressBar.registerHandler(id, handler);
1002 * @return true if any progress bars are still active
1005 public boolean operationInProgress()
1007 return progressBar == null ? false : progressBar.operationInProgress();
1011 * Sets the text of the status bar. Note that setting a null or empty value
1012 * will cause the status bar to be hidden, with possibly undesirable flicker
1013 * of the screen layout.
1016 public void setStatus(String text)
1018 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1022 * Added so Castor Mapping file can obtain Jalview Version
1024 public String getVersion()
1026 return Cache.getProperty("VERSION");
1029 public FeatureRenderer getFeatureRenderer()
1031 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1035 public void fetchSequence_actionPerformed()
1037 new SequenceFetcher(this);
1041 public void addFromFile_actionPerformed(ActionEvent e)
1043 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1047 public void reload_actionPerformed(ActionEvent e)
1049 if (fileName != null)
1051 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1052 // originating file's format
1053 // TODO: work out how to recover feature settings for correct view(s) when
1054 // file is reloaded.
1055 if (FileFormat.Jalview.equals(currentFileFormat))
1057 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1058 for (int i = 0; i < frames.length; i++)
1060 if (frames[i] instanceof AlignFrame && frames[i] != this
1061 && ((AlignFrame) frames[i]).fileName != null
1062 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1066 frames[i].setSelected(true);
1067 Desktop.instance.closeAssociatedWindows();
1068 } catch (java.beans.PropertyVetoException ex)
1074 Desktop.instance.closeAssociatedWindows();
1076 FileLoader loader = new FileLoader();
1077 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1078 ? DataSourceType.URL
1079 : DataSourceType.FILE;
1080 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1084 Rectangle bounds = this.getBounds();
1086 FileLoader loader = new FileLoader();
1088 AlignFrame newframe = null;
1090 if (fileObject == null)
1093 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1094 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1095 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1100 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1101 DataSourceType.FILE, currentFileFormat);
1104 newframe.setBounds(bounds);
1105 if (featureSettings != null && featureSettings.isShowing())
1107 final Rectangle fspos = featureSettings.frame.getBounds();
1108 // TODO: need a 'show feature settings' function that takes bounds -
1109 // need to refactor Desktop.addFrame
1110 newframe.featureSettings_actionPerformed(null);
1111 final FeatureSettings nfs = newframe.featureSettings;
1112 SwingUtilities.invokeLater(new Runnable()
1117 nfs.frame.setBounds(fspos);
1120 this.featureSettings.close();
1121 this.featureSettings = null;
1123 this.closeMenuItem_actionPerformed(true);
1129 public void addFromText_actionPerformed(ActionEvent e)
1132 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1136 public void addFromURL_actionPerformed(ActionEvent e)
1138 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1142 public void save_actionPerformed(ActionEvent e)
1144 if (fileName == null || (currentFileFormat == null)
1145 || HttpUtils.startsWithHttpOrHttps(fileName))
1147 saveAs_actionPerformed();
1151 saveAlignment(fileName, currentFileFormat);
1156 * Saves the alignment to a file with a name chosen by the user, if necessary
1157 * warning if a file would be overwritten
1160 public void saveAs_actionPerformed()
1162 String format = currentFileFormat == null ? null
1163 : currentFileFormat.getName();
1164 JalviewFileChooser chooser = JalviewFileChooser
1165 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1167 chooser.setFileView(new JalviewFileView());
1168 chooser.setDialogTitle(
1169 MessageManager.getString("label.save_alignment_to_file"));
1170 chooser.setToolTipText(MessageManager.getString("action.save"));
1172 int value = chooser.showSaveDialog(this);
1174 if (value != JalviewFileChooser.APPROVE_OPTION)
1178 currentFileFormat = chooser.getSelectedFormat();
1179 // todo is this (2005) test now obsolete - value is never null?
1180 while (currentFileFormat == null)
1182 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1184 .getString("label.select_file_format_before_saving"),
1185 MessageManager.getString("label.file_format_not_specified"),
1186 JvOptionPane.WARNING_MESSAGE);
1187 currentFileFormat = chooser.getSelectedFormat();
1188 value = chooser.showSaveDialog(this);
1189 if (value != JalviewFileChooser.APPROVE_OPTION)
1195 fileName = chooser.getSelectedFile().getPath();
1197 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1198 Cache.setProperty("LAST_DIRECTORY", fileName);
1199 saveAlignment(fileName, currentFileFormat);
1202 boolean lastSaveSuccessful = false;
1204 FileFormatI lastFormatSaved;
1206 String lastFilenameSaved;
1209 * Raise a dialog or status message for the last call to saveAlignment.
1211 * @return true if last call to saveAlignment(file, format) was successful.
1213 public boolean isSaveAlignmentSuccessful()
1216 if (!lastSaveSuccessful)
1218 if (!Platform.isHeadless())
1220 JvOptionPane.showInternalMessageDialog(this, MessageManager
1221 .formatMessage("label.couldnt_save_file", new Object[]
1222 { lastFilenameSaved }),
1223 MessageManager.getString("label.error_saving_file"),
1224 JvOptionPane.WARNING_MESSAGE);
1228 Console.error(MessageManager
1229 .formatMessage("label.couldnt_save_file", new Object[]
1230 { lastFilenameSaved }));
1236 setStatus(MessageManager.formatMessage(
1237 "label.successfully_saved_to_file_in_format", new Object[]
1238 { lastFilenameSaved, lastFormatSaved }));
1241 return lastSaveSuccessful;
1245 * Saves the alignment to the specified file path, in the specified format,
1246 * which may be an alignment format, or Jalview project format. If the
1247 * alignment has hidden regions, or the format is one capable of including
1248 * non-sequence data (features, annotations, groups), then the user may be
1249 * prompted to specify what to include in the output.
1254 public void saveAlignment(String file, FileFormatI format)
1256 saveAlignment(file, format, false, false);
1259 public void saveAlignment(String file, FileFormatI format, boolean stdout,
1260 boolean forceBackup)
1262 lastSaveSuccessful = true;
1265 lastFilenameSaved = file;
1267 lastFormatSaved = format;
1269 if (FileFormat.Jalview.equals(format))
1271 String shortName = title;
1272 if (shortName.indexOf(File.separatorChar) > -1)
1274 shortName = shortName
1275 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1277 // TODO deal with stdout=true
1278 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1281 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1282 if (lastSaveSuccessful)
1284 this.getViewport().setSavedUpToDate(true);
1287 statusBar.setText(MessageManager.formatMessage(
1288 "label.successfully_saved_to_file_in_format", new Object[]
1294 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1295 Runnable cancelAction = () -> {
1296 lastSaveSuccessful = false;
1298 Runnable outputAction = () -> {
1299 // todo defer this to inside formatSequences (or later)
1300 AlignmentExportData exportData = viewport.getAlignExportData(options);
1301 String output = new FormatAdapter(alignPanel, options)
1302 .formatSequences(format, exportData.getAlignment(),
1303 exportData.getOmitHidden(),
1304 exportData.getStartEndPostions(),
1305 viewport.getAlignment().getHiddenColumns());
1308 lastSaveSuccessful = false;
1312 // create backupfiles object and get new temp filename destination
1313 boolean doBackup = forceBackup
1314 || (BackupFiles.getEnabled() && !stdout);
1315 BackupFiles backupfiles = null;
1318 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1319 backupfiles = new BackupFiles(file);
1323 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1325 Console.trace("ALIGNFRAME setting PrintWriter");
1326 PrintWriter out = stdout
1327 ? new PrintWriter(new OutputStreamWriter(System.out))
1328 : new PrintWriter(new FileWriter(tempFilePath));
1330 if (backupfiles != null)
1332 Console.trace("ALIGNFRAME about to write to temp file "
1333 + backupfiles.getTempFilePath());
1340 Console.trace("ALIGNFRAME about to close file");
1342 Console.trace("ALIGNFRAME closed file");
1344 AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
1347 statusBar.setText(MessageManager.formatMessage(
1348 "label.successfully_printed_to_stdout_in_format",
1350 { format.getName() }));
1354 statusBar.setText(MessageManager.formatMessage(
1355 "label.successfully_saved_to_file_in_format",
1357 { fileName, format.getName() }));
1359 lastSaveSuccessful = true;
1360 } catch (IOException e)
1362 lastSaveSuccessful = false;
1364 "ALIGNFRAME Something happened writing the temp file");
1365 Console.error(e.getMessage());
1366 Console.debug(Cache.getStackTraceString(e));
1367 } catch (Exception ex)
1369 lastSaveSuccessful = false;
1371 "ALIGNFRAME Something unexpected happened writing the temp file");
1372 Console.error(ex.getMessage());
1373 Console.debug(Cache.getStackTraceString(ex));
1378 backupfiles.setWriteSuccess(lastSaveSuccessful);
1379 Console.debug("ALIGNFRAME writing temp file was "
1380 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1381 // do the backup file roll and rename the temp file to actual file
1382 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1383 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1384 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1385 + (lastSaveSuccessful ? "" : "un") + "successfully");
1388 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1389 if (lastSaveSuccessful)
1391 AlignFrame.this.getViewport().setSavedUpToDate(true);
1397 * show dialog with export options if applicable; else just do it
1399 if (AlignExportOptions.isNeeded(viewport, format))
1401 AlignExportOptions choices = new AlignExportOptions(
1402 alignPanel.getAlignViewport(), format, options);
1403 choices.setResponseAction(0, outputAction);
1404 choices.setResponseAction(1, cancelAction);
1405 choices.showDialog();
1412 } catch (Exception e)
1414 // TODO Auto-generated catch block
1415 e.printStackTrace();
1421 * Outputs the alignment to textbox in the requested format, if necessary
1422 * first prompting the user for whether to include hidden regions or
1425 * @param fileFormatName
1428 protected void outputText_actionPerformed(String fileFormatName)
1430 FileFormatI fileFormat = FileFormats.getInstance()
1431 .forName(fileFormatName);
1432 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1433 Runnable outputAction = () -> {
1434 // todo defer this to inside formatSequences (or later)
1435 AlignmentExportData exportData = viewport.getAlignExportData(options);
1436 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1437 cap.setForInput(null);
1440 FileFormatI format = fileFormat;
1441 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1442 format, exportData.getAlignment(),
1443 exportData.getOmitHidden(),
1444 exportData.getStartEndPostions(),
1445 viewport.getAlignment().getHiddenColumns()));
1446 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1447 "label.alignment_output_command", new Object[]
1448 { fileFormat.getName() }), 600, 500);
1449 } catch (OutOfMemoryError oom)
1451 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1458 * show dialog with export options if applicable; else just do it
1460 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1462 AlignExportOptions choices = new AlignExportOptions(
1463 alignPanel.getAlignViewport(), fileFormat, options);
1464 choices.setResponseAction(0, outputAction);
1465 choices.showDialog();
1472 } catch (Exception e)
1474 e.printStackTrace();
1486 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1488 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1491 htmlSVG.exportHTML(null);
1492 } catch (ImageOutputException x)
1494 // report problem to console and raise dialog
1499 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1501 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1504 bjs.exportHTML(null);
1505 } catch (ImageOutputException x)
1507 // report problem to console and raise dialog
1511 public void createImageMap(File file, String image)
1515 alignPanel.makePNGImageMap(file, image);
1516 } catch (ImageOutputException x)
1518 // report problem to console and raise dialog
1523 public void createPNG_actionPerformed(ActionEvent e)
1528 } catch (ImageOutputException ioex)
1530 // raise dialog, and report via console
1535 public void createEPS_actionPerformed(ActionEvent e)
1540 } catch (ImageOutputException ioex)
1542 // raise dialog, and report via console
1548 public void createSVG_actionPerformed(ActionEvent e)
1553 } catch (ImageOutputException ioex)
1555 // raise dialog, and report via console
1561 * Creates a PNG image of the alignment and writes it to the given file. If
1562 * the file is null, the user is prompted to choose a file.
1566 public void createPNG(File f) throws ImageOutputException
1568 createPNG(f, null, BitmapImageSizing.defaultBitmapImageSizing());
1571 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1572 throws ImageOutputException
1574 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1578 * Creates an EPS image of the alignment and writes it to the given file. If
1579 * the file is null, the user is prompted to choose a file.
1583 public void createEPS(File f) throws ImageOutputException
1588 public void createEPS(File f, String renderer) throws ImageOutputException
1590 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1594 * Creates an SVG image of the alignment and writes it to the given file. If
1595 * the file is null, the user is prompted to choose a file.
1599 public void createSVG(File f) throws ImageOutputException
1604 public void createSVG(File f, String renderer) throws ImageOutputException
1606 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1610 public void pageSetup_actionPerformed(ActionEvent e)
1612 PrinterJob printJob = PrinterJob.getPrinterJob();
1613 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1623 public void printMenuItem_actionPerformed(ActionEvent e)
1625 // Putting in a thread avoids Swing painting problems
1626 PrintThread thread = new PrintThread(alignPanel);
1631 public void exportFeatures_actionPerformed(ActionEvent e)
1633 new AnnotationExporter(alignPanel).exportFeatures();
1637 public void exportAnnotations_actionPerformed(ActionEvent e)
1639 new AnnotationExporter(alignPanel).exportAnnotations();
1643 public void associatedData_actionPerformed(ActionEvent e)
1645 final JalviewFileChooser chooser = new JalviewFileChooser(
1646 Cache.getProperty("LAST_DIRECTORY"));
1647 chooser.setFileView(new JalviewFileView());
1648 String tooltip = MessageManager
1649 .getString("label.load_jalview_annotations");
1650 chooser.setDialogTitle(tooltip);
1651 chooser.setToolTipText(tooltip);
1652 chooser.setResponseHandler(0, () -> {
1653 String choice = chooser.getSelectedFile().getPath();
1654 Cache.setProperty("LAST_DIRECTORY", choice);
1655 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1658 chooser.showOpenDialog(this);
1662 * Close the current view or all views in the alignment frame. If the frame
1663 * only contains one view then the alignment will be removed from memory.
1665 * @param closeAllTabs
1668 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1670 if (alignPanels != null && alignPanels.size() < 2)
1672 closeAllTabs = true;
1675 Desktop.closeModal(this);
1679 if (alignPanels != null)
1683 if (this.isClosed())
1685 // really close all the windows - otherwise wait till
1686 // setClosed(true) is called
1687 for (int i = 0; i < alignPanels.size(); i++)
1689 AlignmentPanel ap = alignPanels.get(i);
1696 closeView(alignPanel);
1701 if (featureSettings != null && featureSettings.isOpen())
1703 featureSettings.close();
1704 featureSettings = null;
1708 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1709 * be called recursively, with the frame now in 'closed' state
1711 this.setClosed(true);
1713 } catch (Exception ex)
1715 ex.printStackTrace();
1720 * Close the specified panel and close up tabs appropriately.
1722 * @param panelToClose
1724 public void closeView(AlignmentPanel panelToClose)
1726 int index = tabbedPane.getSelectedIndex();
1727 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1728 alignPanels.remove(panelToClose);
1729 panelToClose.closePanel();
1730 panelToClose = null;
1732 tabbedPane.removeTabAt(closedindex);
1733 tabbedPane.validate();
1735 if (index > closedindex || index == tabbedPane.getTabCount())
1737 // modify currently selected tab index if necessary.
1741 this.tabSelectionChanged(index);
1747 void updateEditMenuBar()
1750 if (viewport.getHistoryList().size() > 0)
1752 undoMenuItem.setEnabled(true);
1753 CommandI command = viewport.getHistoryList().peek();
1754 undoMenuItem.setText(MessageManager
1755 .formatMessage("label.undo_command", new Object[]
1756 { command.getDescription() }));
1760 undoMenuItem.setEnabled(false);
1761 undoMenuItem.setText(MessageManager.getString("action.undo"));
1764 if (viewport.getRedoList().size() > 0)
1766 redoMenuItem.setEnabled(true);
1768 CommandI command = viewport.getRedoList().peek();
1769 redoMenuItem.setText(MessageManager
1770 .formatMessage("label.redo_command", new Object[]
1771 { command.getDescription() }));
1775 redoMenuItem.setEnabled(false);
1776 redoMenuItem.setText(MessageManager.getString("action.redo"));
1781 public void addHistoryItem(CommandI command)
1783 if (command.getSize() > 0)
1785 viewport.addToHistoryList(command);
1786 viewport.clearRedoList();
1787 updateEditMenuBar();
1788 viewport.updateHiddenColumns();
1789 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1790 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1791 // viewport.getColumnSelection()
1792 // .getHiddenColumns().size() > 0);
1798 * @return alignment objects for all views
1800 public AlignmentI[] getViewAlignments()
1802 if (alignPanels != null)
1804 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1806 for (AlignmentPanel ap : alignPanels)
1808 als[i++] = ap.av.getAlignment();
1812 if (viewport != null)
1814 return new AlignmentI[] { viewport.getAlignment() };
1826 protected void undoMenuItem_actionPerformed(ActionEvent e)
1828 if (viewport.getHistoryList().isEmpty())
1832 CommandI command = viewport.getHistoryList().pop();
1833 viewport.addToRedoList(command);
1834 command.undoCommand(getViewAlignments());
1836 AlignmentViewport originalSource = getOriginatingSource(command);
1837 updateEditMenuBar();
1839 if (originalSource != null)
1841 if (originalSource != viewport)
1844 "Implementation worry: mismatch of viewport origin for undo");
1846 originalSource.updateHiddenColumns();
1847 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1849 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1850 // viewport.getColumnSelection()
1851 // .getHiddenColumns().size() > 0);
1852 originalSource.firePropertyChange("alignment", null,
1853 originalSource.getAlignment().getSequences());
1864 protected void redoMenuItem_actionPerformed(ActionEvent e)
1866 if (viewport.getRedoList().size() < 1)
1871 CommandI command = viewport.getRedoList().pop();
1872 viewport.addToHistoryList(command);
1873 command.doCommand(getViewAlignments());
1875 AlignmentViewport originalSource = getOriginatingSource(command);
1876 updateEditMenuBar();
1878 if (originalSource != null)
1881 if (originalSource != viewport)
1884 "Implementation worry: mismatch of viewport origin for redo");
1886 originalSource.updateHiddenColumns();
1887 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1889 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1890 // viewport.getColumnSelection()
1891 // .getHiddenColumns().size() > 0);
1892 originalSource.firePropertyChange("alignment", null,
1893 originalSource.getAlignment().getSequences());
1897 AlignmentViewport getOriginatingSource(CommandI command)
1899 AlignmentViewport originalSource = null;
1900 // For sequence removal and addition, we need to fire
1901 // the property change event FROM the viewport where the
1902 // original alignment was altered
1903 AlignmentI al = null;
1904 if (command instanceof EditCommand)
1906 EditCommand editCommand = (EditCommand) command;
1907 al = editCommand.getAlignment();
1908 List<Component> comps = PaintRefresher.components
1909 .get(viewport.getSequenceSetId());
1911 for (Component comp : comps)
1913 if (comp instanceof AlignmentPanel)
1915 if (al == ((AlignmentPanel) comp).av.getAlignment())
1917 originalSource = ((AlignmentPanel) comp).av;
1924 if (originalSource == null)
1926 // The original view is closed, we must validate
1927 // the current view against the closed view first
1930 PaintRefresher.validateSequences(al, viewport.getAlignment());
1933 originalSource = viewport;
1936 return originalSource;
1940 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1941 * or the sequence under cursor in keyboard mode
1946 public void moveSelectedSequences(boolean up)
1948 SequenceGroup sg = viewport.getSelectionGroup();
1952 if (viewport.cursorMode)
1954 sg = new SequenceGroup();
1955 sg.addSequence(viewport.getAlignment().getSequenceAt(
1956 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1964 if (sg.getSize() < 1)
1969 // TODO: JAL-3733 - add an event to the undo buffer for this !
1971 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1972 viewport.getHiddenRepSequences(), up);
1973 alignPanel.paintAlignment(true, false);
1976 synchronized void slideSequences(boolean right, int size)
1978 List<SequenceI> sg = new ArrayList<>();
1979 if (viewport.cursorMode)
1981 sg.add(viewport.getAlignment()
1982 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1984 else if (viewport.getSelectionGroup() != null
1985 && viewport.getSelectionGroup().getSize() != viewport
1986 .getAlignment().getHeight())
1988 sg = viewport.getSelectionGroup()
1989 .getSequences(viewport.getHiddenRepSequences());
1997 List<SequenceI> invertGroup = new ArrayList<>();
1999 for (SequenceI seq : viewport.getAlignment().getSequences())
2001 if (!sg.contains(seq))
2003 invertGroup.add(seq);
2007 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
2009 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2010 for (int i = 0; i < invertGroup.size(); i++)
2012 seqs2[i] = invertGroup.get(i);
2015 SlideSequencesCommand ssc;
2018 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2019 viewport.getGapCharacter());
2023 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2024 viewport.getGapCharacter());
2027 int groupAdjustment = 0;
2028 if (ssc.getGapsInsertedBegin() && right)
2030 if (viewport.cursorMode)
2032 alignPanel.getSeqPanel().moveCursor(size, 0);
2036 groupAdjustment = size;
2039 else if (!ssc.getGapsInsertedBegin() && !right)
2041 if (viewport.cursorMode)
2043 alignPanel.getSeqPanel().moveCursor(-size, 0);
2047 groupAdjustment = -size;
2051 if (groupAdjustment != 0)
2053 viewport.getSelectionGroup().setStartRes(
2054 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2055 viewport.getSelectionGroup().setEndRes(
2056 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2060 * just extend the last slide command if compatible; but not if in
2061 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2063 boolean appendHistoryItem = false;
2064 Deque<CommandI> historyList = viewport.getHistoryList();
2065 boolean inSplitFrame = getSplitViewContainer() != null;
2066 if (!inSplitFrame && historyList != null && historyList.size() > 0
2067 && historyList.peek() instanceof SlideSequencesCommand)
2069 appendHistoryItem = ssc.appendSlideCommand(
2070 (SlideSequencesCommand) historyList.peek());
2073 if (!appendHistoryItem)
2075 addHistoryItem(ssc);
2088 protected void copy_actionPerformed()
2090 if (viewport.getSelectionGroup() == null)
2094 // TODO: preserve the ordering of displayed alignment annotation in any
2095 // internal paste (particularly sequence associated annotation)
2096 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2097 String[] omitHidden = null;
2099 if (viewport.hasHiddenColumns())
2101 omitHidden = viewport.getViewAsString(true);
2104 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2105 seqs, omitHidden, null);
2107 StringSelection ss = new StringSelection(output);
2111 jalview.gui.Desktop.internalCopy = true;
2112 // Its really worth setting the clipboard contents
2113 // to empty before setting the large StringSelection!!
2114 Toolkit.getDefaultToolkit().getSystemClipboard()
2115 .setContents(new StringSelection(""), null);
2117 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2119 } catch (OutOfMemoryError er)
2121 new OOMWarning("copying region", er);
2125 HiddenColumns hiddenColumns = null;
2126 if (viewport.hasHiddenColumns())
2128 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2129 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2131 // create new HiddenColumns object with copy of hidden regions
2132 // between startRes and endRes, offset by startRes
2133 hiddenColumns = new HiddenColumns(
2134 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2135 hiddenCutoff, hiddenOffset);
2138 Desktop.jalviewClipboard = new Object[] { seqs,
2139 viewport.getAlignment().getDataset(), hiddenColumns };
2140 setStatus(MessageManager.formatMessage(
2141 "label.copied_sequences_to_clipboard", new Object[]
2142 { Integer.valueOf(seqs.length).toString() }));
2152 protected void pasteNew_actionPerformed(ActionEvent e)
2164 protected void pasteThis_actionPerformed(ActionEvent e)
2170 * Paste contents of Jalview clipboard
2172 * @param newAlignment
2173 * true to paste to a new alignment, otherwise add to this.
2175 void paste(boolean newAlignment)
2177 boolean externalPaste = true;
2180 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2181 Transferable contents = c.getContents(this);
2183 if (contents == null)
2192 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2193 if (str.length() < 1)
2198 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2200 } catch (OutOfMemoryError er)
2202 new OOMWarning("Out of memory pasting sequences!!", er);
2206 SequenceI[] sequences;
2207 boolean annotationAdded = false;
2208 AlignmentI alignment = null;
2210 if (Desktop.jalviewClipboard != null)
2212 // The clipboard was filled from within Jalview, we must use the
2214 // And dataset from the copied alignment
2215 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2216 // be doubly sure that we create *new* sequence objects.
2217 sequences = new SequenceI[newseq.length];
2218 for (int i = 0; i < newseq.length; i++)
2220 sequences[i] = new Sequence(newseq[i]);
2222 alignment = new Alignment(sequences);
2223 externalPaste = false;
2227 // parse the clipboard as an alignment.
2228 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2230 sequences = alignment.getSequencesArray();
2234 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2240 if (Desktop.jalviewClipboard != null)
2242 // dataset is inherited
2243 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2247 // new dataset is constructed
2248 alignment.setDataset(null);
2250 alwidth = alignment.getWidth() + 1;
2254 AlignmentI pastedal = alignment; // preserve pasted alignment object
2255 // Add pasted sequences and dataset into existing alignment.
2256 alignment = viewport.getAlignment();
2257 alwidth = alignment.getWidth() + 1;
2258 // decide if we need to import sequences from an existing dataset
2259 boolean importDs = Desktop.jalviewClipboard != null
2260 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2261 // importDs==true instructs us to copy over new dataset sequences from
2262 // an existing alignment
2263 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2265 // minimum dataset set
2267 for (int i = 0; i < sequences.length; i++)
2271 newDs.addElement(null);
2273 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2275 if (importDs && ds != null)
2277 if (!newDs.contains(ds))
2279 newDs.setElementAt(ds, i);
2280 ds = new Sequence(ds);
2281 // update with new dataset sequence
2282 sequences[i].setDatasetSequence(ds);
2286 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2291 // copy and derive new dataset sequence
2292 sequences[i] = sequences[i].deriveSequence();
2293 alignment.getDataset()
2294 .addSequence(sequences[i].getDatasetSequence());
2295 // TODO: avoid creation of duplicate dataset sequences with a
2296 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2298 alignment.addSequence(sequences[i]); // merges dataset
2302 newDs.clear(); // tidy up
2304 if (alignment.getAlignmentAnnotation() != null)
2306 for (AlignmentAnnotation alan : alignment
2307 .getAlignmentAnnotation())
2309 if (alan.graphGroup > fgroup)
2311 fgroup = alan.graphGroup;
2315 if (pastedal.getAlignmentAnnotation() != null)
2317 // Add any annotation attached to alignment.
2318 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2319 for (int i = 0; i < alann.length; i++)
2321 annotationAdded = true;
2322 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2324 AlignmentAnnotation newann = new AlignmentAnnotation(
2326 if (newann.graphGroup > -1)
2328 if (newGraphGroups.size() <= newann.graphGroup
2329 || newGraphGroups.get(newann.graphGroup) == null)
2331 for (int q = newGraphGroups
2332 .size(); q <= newann.graphGroup; q++)
2334 newGraphGroups.add(q, null);
2336 newGraphGroups.set(newann.graphGroup,
2337 Integer.valueOf(++fgroup));
2339 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2343 newann.padAnnotation(alwidth);
2344 alignment.addAnnotation(newann);
2354 addHistoryItem(new EditCommand(
2355 MessageManager.getString("label.add_sequences"),
2356 Action.PASTE, sequences, 0, alignment.getWidth(),
2359 // Add any annotations attached to sequences
2360 for (int i = 0; i < sequences.length; i++)
2362 if (sequences[i].getAnnotation() != null)
2364 AlignmentAnnotation newann;
2365 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2367 annotationAdded = true;
2368 newann = sequences[i].getAnnotation()[a];
2369 newann.adjustForAlignment();
2370 newann.padAnnotation(alwidth);
2371 if (newann.graphGroup > -1)
2373 if (newann.graphGroup > -1)
2375 if (newGraphGroups.size() <= newann.graphGroup
2376 || newGraphGroups.get(newann.graphGroup) == null)
2378 for (int q = newGraphGroups
2379 .size(); q <= newann.graphGroup; q++)
2381 newGraphGroups.add(q, null);
2383 newGraphGroups.set(newann.graphGroup,
2384 Integer.valueOf(++fgroup));
2386 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2390 // annotation was duplicated earlier
2391 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2392 // take care of contact matrix too
2393 ContactMatrixI cm = sequences[i]
2394 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2397 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2401 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2409 // propagate alignment changed.
2410 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2411 if (annotationAdded)
2413 // Duplicate sequence annotation in all views.
2414 AlignmentI[] alview = this.getViewAlignments();
2415 for (int i = 0; i < sequences.length; i++)
2417 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2422 for (int avnum = 0; avnum < alview.length; avnum++)
2424 if (alview[avnum] != alignment)
2426 // duplicate in a view other than the one with input focus
2427 int avwidth = alview[avnum].getWidth() + 1;
2428 // this relies on sann being preserved after we
2429 // modify the sequence's annotation array for each duplication
2430 for (int a = 0; a < sann.length; a++)
2432 AlignmentAnnotation newann = new AlignmentAnnotation(
2434 sequences[i].addAlignmentAnnotation(newann);
2435 newann.padAnnotation(avwidth);
2436 alview[avnum].addAnnotation(newann); // annotation was
2437 // duplicated earlier
2438 // TODO JAL-1145 graphGroups are not updated for sequence
2439 // annotation added to several views. This may cause
2441 alview[avnum].setAnnotationIndex(newann, a);
2446 buildSortByAnnotationScoresMenu();
2448 viewport.firePropertyChange("alignment", null,
2449 alignment.getSequences());
2450 if (alignPanels != null)
2452 for (AlignmentPanel ap : alignPanels)
2454 ap.validateAnnotationDimensions(false);
2459 alignPanel.validateAnnotationDimensions(false);
2465 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2467 String newtitle = new String("Copied sequences");
2469 if (Desktop.jalviewClipboard != null
2470 && Desktop.jalviewClipboard[2] != null)
2472 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2473 af.viewport.setHiddenColumns(hc);
2476 // >>>This is a fix for the moment, until a better solution is
2478 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2479 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2480 .getFeatureRenderer());
2482 // TODO: maintain provenance of an alignment, rather than just make the
2483 // title a concatenation of operations.
2486 if (title.startsWith("Copied sequences"))
2492 newtitle = newtitle.concat("- from " + title);
2497 newtitle = new String("Pasted sequences");
2500 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2505 } catch (Exception ex)
2507 ex.printStackTrace();
2508 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2509 // could be anything being pasted in here
2515 protected void expand_newalign(ActionEvent e)
2519 AlignmentI alignment = AlignmentUtils
2520 .expandContext(getViewport().getAlignment(), -1);
2521 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2523 String newtitle = new String("Flanking alignment");
2525 if (Desktop.jalviewClipboard != null
2526 && Desktop.jalviewClipboard[2] != null)
2528 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2529 af.viewport.setHiddenColumns(hc);
2532 // >>>This is a fix for the moment, until a better solution is
2534 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2535 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2536 .getFeatureRenderer());
2538 // TODO: maintain provenance of an alignment, rather than just make the
2539 // title a concatenation of operations.
2541 if (title.startsWith("Copied sequences"))
2547 newtitle = newtitle.concat("- from " + title);
2551 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2553 } catch (Exception ex)
2555 ex.printStackTrace();
2556 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2557 // could be anything being pasted in here
2558 } catch (OutOfMemoryError oom)
2560 new OOMWarning("Viewing flanking region of alignment", oom);
2565 * Action Cut (delete and copy) the selected region
2568 protected void cut_actionPerformed()
2570 copy_actionPerformed();
2571 delete_actionPerformed();
2575 * Performs menu option to Delete the currently selected region
2578 protected void delete_actionPerformed()
2581 SequenceGroup sg = viewport.getSelectionGroup();
2587 Runnable okAction = () -> {
2588 SequenceI[] cut = sg.getSequences()
2589 .toArray(new SequenceI[sg.getSize()]);
2591 addHistoryItem(new EditCommand(
2592 MessageManager.getString("label.cut_sequences"), Action.CUT,
2593 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2594 viewport.getAlignment()));
2596 viewport.setSelectionGroup(null);
2597 viewport.sendSelection();
2598 viewport.getAlignment().deleteGroup(sg);
2600 viewport.firePropertyChange("alignment", null,
2601 viewport.getAlignment().getSequences());
2602 if (viewport.getAlignment().getHeight() < 1)
2606 AlignFrame.this.setClosed(true);
2607 } catch (Exception ex)
2614 * If the cut affects all sequences, prompt for confirmation
2616 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2618 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2619 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2620 if (wholeHeight && wholeWidth)
2622 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2623 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2624 Object[] options = new Object[] {
2625 MessageManager.getString("action.ok"),
2626 MessageManager.getString("action.cancel") };
2627 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2628 MessageManager.getString("label.delete_all"),
2629 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2630 options, options[0]);
2637 } catch (Exception e)
2639 e.printStackTrace();
2651 protected void deleteGroups_actionPerformed(ActionEvent e)
2653 if (avc.deleteGroups())
2655 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2656 alignPanel.updateAnnotation();
2657 alignPanel.paintAlignment(true, true);
2668 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2670 SequenceGroup sg = new SequenceGroup(
2671 viewport.getAlignment().getSequences());
2673 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2674 viewport.setSelectionGroup(sg);
2675 viewport.isSelectionGroupChanged(true);
2676 viewport.sendSelection();
2677 // JAL-2034 - should delegate to
2678 // alignPanel to decide if overview needs
2680 alignPanel.paintAlignment(false, false);
2681 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2691 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2693 if (viewport.cursorMode)
2695 alignPanel.getSeqPanel().keyboardNo1 = null;
2696 alignPanel.getSeqPanel().keyboardNo2 = null;
2698 viewport.setSelectionGroup(null);
2699 viewport.getColumnSelection().clear();
2700 viewport.setSearchResults(null);
2701 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2702 // JAL-2034 - should delegate to
2703 // alignPanel to decide if overview needs
2705 alignPanel.paintAlignment(false, false);
2706 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2707 viewport.sendSelection();
2717 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2719 SequenceGroup sg = viewport.getSelectionGroup();
2723 selectAllSequenceMenuItem_actionPerformed(null);
2728 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2730 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2732 // JAL-2034 - should delegate to
2733 // alignPanel to decide if overview needs
2736 alignPanel.paintAlignment(true, false);
2737 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2738 viewport.sendSelection();
2742 public void invertColSel_actionPerformed(ActionEvent e)
2744 viewport.invertColumnSelection();
2745 alignPanel.paintAlignment(true, false);
2746 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2747 viewport.sendSelection();
2757 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2759 trimAlignment(true);
2769 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2771 trimAlignment(false);
2774 void trimAlignment(boolean trimLeft)
2776 ColumnSelection colSel = viewport.getColumnSelection();
2779 if (!colSel.isEmpty())
2783 column = colSel.getMin();
2787 column = colSel.getMax();
2791 if (viewport.getSelectionGroup() != null)
2793 seqs = viewport.getSelectionGroup()
2794 .getSequencesAsArray(viewport.getHiddenRepSequences());
2798 seqs = viewport.getAlignment().getSequencesArray();
2801 TrimRegionCommand trimRegion;
2804 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2805 column, viewport.getAlignment());
2806 viewport.getRanges().setStartRes(0);
2810 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2811 column, viewport.getAlignment());
2814 setStatus(MessageManager.formatMessage("label.removed_columns",
2816 { Integer.valueOf(trimRegion.getSize()).toString() }));
2818 addHistoryItem(trimRegion);
2820 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2822 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2823 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2825 viewport.getAlignment().deleteGroup(sg);
2829 viewport.firePropertyChange("alignment", null,
2830 viewport.getAlignment().getSequences());
2841 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2843 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2846 if (viewport.getSelectionGroup() != null)
2848 seqs = viewport.getSelectionGroup()
2849 .getSequencesAsArray(viewport.getHiddenRepSequences());
2850 start = viewport.getSelectionGroup().getStartRes();
2851 end = viewport.getSelectionGroup().getEndRes();
2855 seqs = viewport.getAlignment().getSequencesArray();
2858 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2859 "Remove Gapped Columns", seqs, start, end,
2860 viewport.getAlignment());
2862 addHistoryItem(removeGapCols);
2864 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2866 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2868 // This is to maintain viewport position on first residue
2869 // of first sequence
2870 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2871 ViewportRanges ranges = viewport.getRanges();
2872 int startRes = seq.findPosition(ranges.getStartRes());
2873 // ShiftList shifts;
2874 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2875 // edit.alColumnChanges=shifts.getInverse();
2876 // if (viewport.hasHiddenColumns)
2877 // viewport.getColumnSelection().compensateForEdits(shifts);
2878 ranges.setStartRes(seq.findIndex(startRes) - 1);
2879 viewport.firePropertyChange("alignment", null,
2880 viewport.getAlignment().getSequences());
2891 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2893 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2896 if (viewport.getSelectionGroup() != null)
2898 seqs = viewport.getSelectionGroup()
2899 .getSequencesAsArray(viewport.getHiddenRepSequences());
2900 start = viewport.getSelectionGroup().getStartRes();
2901 end = viewport.getSelectionGroup().getEndRes();
2905 seqs = viewport.getAlignment().getSequencesArray();
2908 // This is to maintain viewport position on first residue
2909 // of first sequence
2910 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2911 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2913 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2914 viewport.getAlignment()));
2916 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2918 viewport.firePropertyChange("alignment", null,
2919 viewport.getAlignment().getSequences());
2930 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2932 viewport.setPadGaps(padGapsMenuitem.isSelected());
2933 viewport.firePropertyChange("alignment", null,
2934 viewport.getAlignment().getSequences());
2938 * Opens a Finder dialog
2943 public void findMenuItem_actionPerformed(ActionEvent e)
2945 new Finder(alignPanel, false, null);
2949 * Create a new view of the current alignment.
2952 public void newView_actionPerformed(ActionEvent e)
2954 newView(null, true);
2958 * Creates and shows a new view of the current alignment.
2961 * title of newly created view; if null, one will be generated
2962 * @param copyAnnotation
2963 * if true then duplicate all annnotation, groups and settings
2964 * @return new alignment panel, already displayed.
2966 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2969 * Create a new AlignmentPanel (with its own, new Viewport)
2971 AlignmentPanel newap = new jalview.project.Jalview2XML()
2972 .copyAlignPanel(alignPanel);
2973 if (!copyAnnotation)
2976 * remove all groups and annotation except for the automatic stuff
2978 newap.av.getAlignment().deleteAllGroups();
2979 newap.av.getAlignment().deleteAllAnnotations(false);
2982 newap.av.setGatherViewsHere(false);
2984 if (viewport.getViewName() == null)
2986 viewport.setViewName(
2987 MessageManager.getString("label.view_name_original"));
2991 * Views share the same edits undo and redo stacks
2993 newap.av.setHistoryList(viewport.getHistoryList());
2994 newap.av.setRedoList(viewport.getRedoList());
2997 * copy any visualisation settings that are not saved in the project
2999 newap.av.setColourAppliesToAllGroups(
3000 viewport.getColourAppliesToAllGroups());
3003 * Views share the same mappings; need to deregister any new mappings
3004 * created by copyAlignPanel, and register the new reference to the shared
3007 newap.av.replaceMappings(viewport.getAlignment());
3010 * start up cDNA consensus (if applicable) now mappings are in place
3012 if (newap.av.initComplementConsensus())
3014 newap.refresh(true); // adjust layout of annotations
3017 newap.av.setViewName(getNewViewName(viewTitle));
3019 addAlignmentPanel(newap, true);
3020 newap.alignmentChanged();
3022 if (alignPanels.size() == 2)
3024 viewport.setGatherViewsHere(true);
3026 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3032 * Make a new name for the view, ensuring it is unique within the current
3033 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3034 * these now use viewId. Unique view names are still desirable for usability.)
3039 protected String getNewViewName(String viewTitle)
3041 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3042 boolean addFirstIndex = false;
3043 if (viewTitle == null || viewTitle.trim().length() == 0)
3045 viewTitle = MessageManager.getString("action.view");
3046 addFirstIndex = true;
3050 index = 1;// we count from 1 if given a specific name
3052 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3054 List<Component> comps = PaintRefresher.components
3055 .get(viewport.getSequenceSetId());
3057 List<String> existingNames = getExistingViewNames(comps);
3059 while (existingNames.contains(newViewName))
3061 newViewName = viewTitle + " " + (++index);
3067 * Returns a list of distinct view names found in the given list of
3068 * components. View names are held on the viewport of an AlignmentPanel.
3073 protected List<String> getExistingViewNames(List<Component> comps)
3075 List<String> existingNames = new ArrayList<>();
3076 for (Component comp : comps)
3078 if (comp instanceof AlignmentPanel)
3080 AlignmentPanel ap = (AlignmentPanel) comp;
3081 if (!existingNames.contains(ap.av.getViewName()))
3083 existingNames.add(ap.av.getViewName());
3087 return existingNames;
3091 * Explode tabbed views into separate windows.
3094 public void expandViews_actionPerformed(ActionEvent e)
3096 Desktop.explodeViews(this);
3100 * Gather views in separate windows back into a tabbed presentation.
3103 public void gatherViews_actionPerformed(ActionEvent e)
3105 Desktop.instance.gatherViews(this);
3115 public void font_actionPerformed(ActionEvent e)
3117 new FontChooser(alignPanel);
3127 protected void seqLimit_actionPerformed(ActionEvent e)
3129 viewport.setShowJVSuffix(seqLimits.isSelected());
3131 alignPanel.getIdPanel().getIdCanvas()
3132 .setPreferredSize(alignPanel.calculateIdWidth());
3133 alignPanel.paintAlignment(true, false);
3137 public void idRightAlign_actionPerformed(ActionEvent e)
3139 viewport.setRightAlignIds(idRightAlign.isSelected());
3140 alignPanel.paintAlignment(false, false);
3144 public void centreColumnLabels_actionPerformed(ActionEvent e)
3146 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3147 alignPanel.paintAlignment(false, false);
3153 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3156 protected void followHighlight_actionPerformed()
3159 * Set the 'follow' flag on the Viewport (and scroll to position if now
3162 final boolean state = this.followHighlightMenuItem.getState();
3163 viewport.setFollowHighlight(state);
3166 alignPanel.scrollToPosition(viewport.getSearchResults());
3177 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3179 viewport.setColourText(colourTextMenuItem.isSelected());
3180 alignPanel.paintAlignment(false, false);
3190 public void wrapMenuItem_actionPerformed(ActionEvent e)
3192 setWrapFormat(wrapMenuItem.isSelected(), false);
3195 public void setWrapFormat(boolean b, boolean setMenuItem)
3197 scaleAbove.setVisible(b);
3198 scaleLeft.setVisible(b);
3199 scaleRight.setVisible(b);
3200 viewport.setWrapAlignment(b);
3201 alignPanel.updateLayout();
3204 wrapMenuItem.setSelected(b);
3209 public void showAllSeqs_actionPerformed(ActionEvent e)
3211 viewport.showAllHiddenSeqs();
3215 public void showAllColumns_actionPerformed(ActionEvent e)
3217 viewport.showAllHiddenColumns();
3218 alignPanel.paintAlignment(true, true);
3219 viewport.sendSelection();
3223 public void hideSelSequences_actionPerformed(ActionEvent e)
3225 viewport.hideAllSelectedSeqs();
3229 * called by key handler and the hide all/show all menu items
3234 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3237 boolean hide = false;
3238 SequenceGroup sg = viewport.getSelectionGroup();
3239 if (!toggleSeqs && !toggleCols)
3241 // Hide everything by the current selection - this is a hack - we do the
3242 // invert and then hide
3243 // first check that there will be visible columns after the invert.
3244 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3245 && sg.getStartRes() <= sg.getEndRes()))
3247 // now invert the sequence set, if required - empty selection implies
3248 // that no hiding is required.
3251 invertSequenceMenuItem_actionPerformed(null);
3252 sg = viewport.getSelectionGroup();
3256 viewport.expandColSelection(sg, true);
3257 // finally invert the column selection and get the new sequence
3259 invertColSel_actionPerformed(null);
3266 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3268 hideSelSequences_actionPerformed(null);
3271 else if (!(toggleCols && viewport.hasSelectedColumns()))
3273 showAllSeqs_actionPerformed(null);
3279 if (viewport.hasSelectedColumns())
3281 hideSelColumns_actionPerformed(null);
3284 viewport.setSelectionGroup(sg);
3289 showAllColumns_actionPerformed(null);
3298 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3299 * event.ActionEvent)
3302 public void hideAllButSelection_actionPerformed(ActionEvent e)
3304 toggleHiddenRegions(false, false);
3305 viewport.sendSelection();
3312 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3316 public void hideAllSelection_actionPerformed(ActionEvent e)
3318 SequenceGroup sg = viewport.getSelectionGroup();
3319 viewport.expandColSelection(sg, false);
3320 viewport.hideAllSelectedSeqs();
3321 viewport.hideSelectedColumns();
3322 alignPanel.updateLayout();
3323 alignPanel.paintAlignment(true, true);
3324 viewport.sendSelection();
3331 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3335 public void showAllhidden_actionPerformed(ActionEvent e)
3337 viewport.showAllHiddenColumns();
3338 viewport.showAllHiddenSeqs();
3339 alignPanel.paintAlignment(true, true);
3340 viewport.sendSelection();
3344 public void hideSelColumns_actionPerformed(ActionEvent e)
3346 viewport.hideSelectedColumns();
3347 alignPanel.updateLayout();
3348 alignPanel.paintAlignment(true, true);
3349 viewport.sendSelection();
3353 public void hiddenMarkers_actionPerformed(ActionEvent e)
3355 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3366 protected void scaleAbove_actionPerformed(ActionEvent e)
3368 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3369 alignPanel.updateLayout();
3370 alignPanel.paintAlignment(true, false);
3380 protected void scaleLeft_actionPerformed(ActionEvent e)
3382 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3383 alignPanel.updateLayout();
3384 alignPanel.paintAlignment(true, false);
3394 protected void scaleRight_actionPerformed(ActionEvent e)
3396 viewport.setScaleRightWrapped(scaleRight.isSelected());
3397 alignPanel.updateLayout();
3398 alignPanel.paintAlignment(true, false);
3408 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3410 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3411 alignPanel.paintAlignment(false, false);
3421 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3423 viewport.setShowText(viewTextMenuItem.isSelected());
3424 alignPanel.paintAlignment(false, false);
3434 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3436 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3437 alignPanel.paintAlignment(false, false);
3440 public FeatureSettings featureSettings;
3443 public FeatureSettingsControllerI getFeatureSettingsUI()
3445 return featureSettings;
3449 public void featureSettings_actionPerformed(ActionEvent e)
3451 showFeatureSettingsUI();
3455 public FeatureSettingsControllerI showFeatureSettingsUI()
3457 if (featureSettings != null)
3459 featureSettings.closeOldSettings();
3460 featureSettings = null;
3462 if (!showSeqFeatures.isSelected())
3464 // make sure features are actually displayed
3465 showSeqFeatures.setSelected(true);
3466 showSeqFeatures_actionPerformed(null);
3468 featureSettings = new FeatureSettings(this);
3469 return featureSettings;
3473 * Set or clear 'Show Sequence Features'
3479 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3481 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3482 alignPanel.paintAlignment(true, true);
3486 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3487 * the annotations panel as a whole.
3489 * The options to show/hide all annotations should be enabled when the panel
3490 * is shown, and disabled when the panel is hidden.
3495 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3497 final boolean setVisible = annotationPanelMenuItem.isSelected();
3498 viewport.setShowAnnotation(setVisible);
3499 this.showAllSeqAnnotations.setEnabled(setVisible);
3500 this.hideAllSeqAnnotations.setEnabled(setVisible);
3501 this.showAllAlAnnotations.setEnabled(setVisible);
3502 this.hideAllAlAnnotations.setEnabled(setVisible);
3503 alignPanel.updateLayout();
3507 public void alignmentProperties()
3510 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3513 String content = MessageManager.formatMessage("label.html_content",
3515 { contents.toString() });
3518 if (Platform.isJS())
3520 JLabel textLabel = new JLabel();
3521 textLabel.setText(content);
3522 textLabel.setBackground(Color.WHITE);
3524 pane = new JPanel(new BorderLayout());
3525 ((JPanel) pane).setOpaque(true);
3526 pane.setBackground(Color.WHITE);
3527 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3536 JEditorPane editPane = new JEditorPane("text/html", "");
3537 editPane.setEditable(false);
3538 editPane.setText(content);
3542 JInternalFrame frame = new JInternalFrame();
3543 frame.setFrameIcon(null);
3544 frame.getContentPane().add(new JScrollPane(pane));
3546 Desktop.addInternalFrame(frame, MessageManager
3547 .formatMessage("label.alignment_properties", new Object[]
3548 { getTitle() }), 500, 400);
3552 * Opens an Overview panel for the alignment, unless one is open already
3557 public void overviewMenuItem_actionPerformed(ActionEvent e)
3559 boolean showHiddenRegions = Cache
3560 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3561 openOverviewPanel(showHiddenRegions);
3564 public OverviewPanel openOverviewPanel(boolean showHidden)
3566 if (alignPanel.overviewPanel != null)
3568 return alignPanel.overviewPanel;
3570 JInternalFrame frame = new JInternalFrame();
3571 frame.setFrameIcon(null);
3572 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3574 frame.setContentPane(overview);
3575 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3576 frame.getHeight(), true, true);
3578 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3579 final AlignmentPanel thePanel = this.alignPanel;
3580 frame.addInternalFrameListener(
3581 new javax.swing.event.InternalFrameAdapter()
3584 public void internalFrameClosed(
3585 javax.swing.event.InternalFrameEvent evt)
3588 thePanel.setOverviewPanel(null);
3591 if (getKeyListeners().length > 0)
3593 frame.addKeyListener(getKeyListeners()[0]);
3596 alignPanel.setOverviewPanel(overview);
3597 alignPanel.setOverviewTitle(this);
3603 public void textColour_actionPerformed()
3605 new TextColourChooser().chooseColour(alignPanel, null);
3609 * public void covariationColour_actionPerformed() {
3611 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3615 public void annotationColour_actionPerformed()
3617 new AnnotationColourChooser(viewport, alignPanel);
3621 public void annotationColumn_actionPerformed(ActionEvent e)
3623 new AnnotationColumnChooser(viewport, alignPanel);
3627 * Action on the user checking or unchecking the option to apply the selected
3628 * colour scheme to all groups. If unchecked, groups may have their own
3629 * independent colour schemes.
3634 public void applyToAllGroups_actionPerformed(boolean selected)
3636 viewport.setColourAppliesToAllGroups(selected);
3640 * Action on user selecting a colour from the colour menu
3643 * the name (not the menu item label!) of the colour scheme
3646 public void changeColour_actionPerformed(String name)
3649 * 'User Defined' opens a panel to configure or load a
3650 * user-defined colour scheme
3652 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3654 new UserDefinedColours(alignPanel);
3659 * otherwise set the chosen colour scheme (or null for 'None')
3661 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3662 viewport, viewport.getAlignment(),
3663 viewport.getHiddenRepSequences());
3668 * Actions on setting or changing the alignment colour scheme
3673 public void changeColour(ColourSchemeI cs)
3675 // TODO: pull up to controller method
3676 ColourMenuHelper.setColourSelected(colourMenu, cs);
3678 viewport.setGlobalColourScheme(cs);
3680 alignPanel.paintAlignment(true, true);
3684 * Show the PID threshold slider panel
3687 protected void modifyPID_actionPerformed()
3689 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3690 alignPanel.getViewName());
3691 SliderPanel.showPIDSlider();
3695 * Show the Conservation slider panel
3698 protected void modifyConservation_actionPerformed()
3700 SliderPanel.setConservationSlider(alignPanel,
3701 viewport.getResidueShading(), alignPanel.getViewName());
3702 SliderPanel.showConservationSlider();
3706 * Action on selecting or deselecting (Colour) By Conservation
3709 public void conservationMenuItem_actionPerformed(boolean selected)
3711 modifyConservation.setEnabled(selected);
3712 viewport.setConservationSelected(selected);
3713 viewport.getResidueShading().setConservationApplied(selected);
3715 changeColour(viewport.getGlobalColourScheme());
3718 modifyConservation_actionPerformed();
3722 SliderPanel.hideConservationSlider();
3727 * Action on selecting or deselecting (Colour) Above PID Threshold
3730 public void abovePIDThreshold_actionPerformed(boolean selected)
3732 modifyPID.setEnabled(selected);
3733 viewport.setAbovePIDThreshold(selected);
3736 viewport.getResidueShading().setThreshold(0,
3737 viewport.isIgnoreGapsConsensus());
3740 changeColour(viewport.getGlobalColourScheme());
3743 modifyPID_actionPerformed();
3747 SliderPanel.hidePIDSlider();
3758 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3760 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3761 AlignmentSorter.sortByPID(viewport.getAlignment(),
3762 viewport.getAlignment().getSequenceAt(0));
3763 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3764 viewport.getAlignment()));
3765 alignPanel.paintAlignment(true, false);
3775 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3777 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3778 AlignmentSorter.sortByID(viewport.getAlignment());
3780 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3781 alignPanel.paintAlignment(true, false);
3791 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3793 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3794 AlignmentSorter.sortByLength(viewport.getAlignment());
3795 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3796 viewport.getAlignment()));
3797 alignPanel.paintAlignment(true, false);
3807 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3809 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3810 AlignmentSorter.sortByGroup(viewport.getAlignment());
3811 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3812 viewport.getAlignment()));
3814 alignPanel.paintAlignment(true, false);
3824 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3826 new RedundancyPanel(alignPanel, this);
3836 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3838 if ((viewport.getSelectionGroup() == null)
3839 || (viewport.getSelectionGroup().getSize() < 2))
3841 JvOptionPane.showInternalMessageDialog(this,
3842 MessageManager.getString(
3843 "label.you_must_select_least_two_sequences"),
3844 MessageManager.getString("label.invalid_selection"),
3845 JvOptionPane.WARNING_MESSAGE);
3849 JInternalFrame frame = new JInternalFrame();
3850 frame.setFrameIcon(null);
3851 frame.setContentPane(new PairwiseAlignPanel(viewport));
3852 Desktop.addInternalFrame(frame,
3853 MessageManager.getString("action.pairwise_alignment"), 600,
3859 public void autoCalculate_actionPerformed(ActionEvent e)
3861 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3862 if (viewport.autoCalculateConsensus)
3864 viewport.firePropertyChange("alignment", null,
3865 viewport.getAlignment().getSequences());
3870 public void sortByTreeOption_actionPerformed(ActionEvent e)
3872 viewport.sortByTree = sortByTree.isSelected();
3876 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3878 viewport.followSelection = listenToViewSelections.isSelected();
3882 * Constructs a tree panel and adds it to the desktop
3885 * tree type (NJ or AV)
3887 * name of score model used to compute the tree
3889 * parameters for the distance or similarity calculation
3891 void newTreePanel(String type, String modelName,
3892 SimilarityParamsI options)
3894 String frameTitle = "";
3897 boolean onSelection = false;
3898 if (viewport.getSelectionGroup() != null
3899 && viewport.getSelectionGroup().getSize() > 0)
3901 SequenceGroup sg = viewport.getSelectionGroup();
3903 /* Decide if the selection is a column region */
3904 for (SequenceI _s : sg.getSequences())
3906 if (_s.getLength() < sg.getEndRes())
3908 JvOptionPane.showMessageDialog(Desktop.desktop,
3909 MessageManager.getString(
3910 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3911 MessageManager.getString(
3912 "label.sequences_selection_not_aligned"),
3913 JvOptionPane.WARNING_MESSAGE);
3922 if (viewport.getAlignment().getHeight() < 2)
3928 tp = new TreePanel(alignPanel, type, modelName, options);
3929 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3931 frameTitle += " from ";
3933 if (viewport.getViewName() != null)
3935 frameTitle += viewport.getViewName() + " of ";
3938 frameTitle += this.title;
3940 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3951 public void addSortByOrderMenuItem(String title,
3952 final AlignmentOrder order)
3954 final JMenuItem item = new JMenuItem(MessageManager
3955 .formatMessage("action.by_title_param", new Object[]
3958 item.addActionListener(new java.awt.event.ActionListener()
3961 public void actionPerformed(ActionEvent e)
3963 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3965 // TODO: JBPNote - have to map order entries to curent SequenceI
3967 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3969 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3970 viewport.getAlignment()));
3972 alignPanel.paintAlignment(true, false);
3978 * Add a new sort by annotation score menu item
3981 * the menu to add the option to
3983 * the label used to retrieve scores for each sequence on the
3986 public void addSortByAnnotScoreMenuItem(JMenu sort,
3987 final String scoreLabel)
3989 final JMenuItem item = new JMenuItem(scoreLabel);
3991 item.addActionListener(new java.awt.event.ActionListener()
3994 public void actionPerformed(ActionEvent e)
3996 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3997 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3998 viewport.getAlignment());// ,viewport.getSelectionGroup());
3999 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
4000 viewport.getAlignment()));
4001 alignPanel.paintAlignment(true, false);
4007 * last hash for alignment's annotation array - used to minimise cost of
4010 protected int _annotationScoreVectorHash;
4013 * search the alignment and rebuild the sort by annotation score submenu the
4014 * last alignment annotation vector hash is stored to minimize cost of
4015 * rebuilding in subsequence calls.
4019 public void buildSortByAnnotationScoresMenu()
4021 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4026 if (viewport.getAlignment().getAlignmentAnnotation()
4027 .hashCode() != _annotationScoreVectorHash)
4029 sortByAnnotScore.removeAll();
4030 // almost certainly a quicker way to do this - but we keep it simple
4031 Hashtable<String, String> scoreSorts = new Hashtable<>();
4032 AlignmentAnnotation aann[];
4033 for (SequenceI sqa : viewport.getAlignment().getSequences())
4035 aann = sqa.getAnnotation();
4036 for (int i = 0; aann != null && i < aann.length; i++)
4038 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4040 scoreSorts.put(aann[i].label, aann[i].label);
4044 Enumeration<String> labels = scoreSorts.keys();
4045 while (labels.hasMoreElements())
4047 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4049 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4052 _annotationScoreVectorHash = viewport.getAlignment()
4053 .getAlignmentAnnotation().hashCode();
4058 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4059 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4060 * call. Listeners are added to remove the menu item when the treePanel is
4061 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4065 public void buildTreeSortMenu()
4067 sortByTreeMenu.removeAll();
4069 List<Component> comps = PaintRefresher.components
4070 .get(viewport.getSequenceSetId());
4071 List<TreePanel> treePanels = new ArrayList<>();
4072 for (Component comp : comps)
4074 if (comp instanceof TreePanel)
4076 treePanels.add((TreePanel) comp);
4080 if (treePanels.size() < 1)
4082 sortByTreeMenu.setVisible(false);
4086 sortByTreeMenu.setVisible(true);
4088 for (final TreePanel tp : treePanels)
4090 final JMenuItem item = new JMenuItem(tp.getTitle());
4091 item.addActionListener(new java.awt.event.ActionListener()
4094 public void actionPerformed(ActionEvent e)
4096 tp.sortByTree_actionPerformed();
4097 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4102 sortByTreeMenu.add(item);
4106 public boolean sortBy(AlignmentOrder alorder, String undoname)
4108 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4109 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4110 if (undoname != null)
4112 addHistoryItem(new OrderCommand(undoname, oldOrder,
4113 viewport.getAlignment()));
4115 alignPanel.paintAlignment(true, false);
4120 * Work out whether the whole set of sequences or just the selected set will
4121 * be submitted for multiple alignment.
4124 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4126 // Now, check we have enough sequences
4127 AlignmentView msa = null;
4129 if ((viewport.getSelectionGroup() != null)
4130 && (viewport.getSelectionGroup().getSize() > 1))
4132 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4133 // some common interface!
4135 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4136 * SequenceI[sz = seqs.getSize(false)];
4138 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4139 * seqs.getSequenceAt(i); }
4141 msa = viewport.getAlignmentView(true);
4143 else if (viewport.getSelectionGroup() != null
4144 && viewport.getSelectionGroup().getSize() == 1)
4146 int option = JvOptionPane.showConfirmDialog(this,
4147 MessageManager.getString("warn.oneseq_msainput_selection"),
4148 MessageManager.getString("label.invalid_selection"),
4149 JvOptionPane.OK_CANCEL_OPTION);
4150 if (option == JvOptionPane.OK_OPTION)
4152 msa = viewport.getAlignmentView(false);
4157 msa = viewport.getAlignmentView(false);
4163 * Decides what is submitted to a secondary structure prediction service: the
4164 * first sequence in the alignment, or in the current selection, or, if the
4165 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4166 * region or the whole alignment. (where the first sequence in the set is the
4167 * one that the prediction will be for).
4169 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4171 AlignmentView seqs = null;
4173 if ((viewport.getSelectionGroup() != null)
4174 && (viewport.getSelectionGroup().getSize() > 0))
4176 seqs = viewport.getAlignmentView(true);
4180 seqs = viewport.getAlignmentView(false);
4182 // limit sequences - JBPNote in future - could spawn multiple prediction
4184 // TODO: viewport.getAlignment().isAligned is a global state - the local
4185 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4186 if (!viewport.getAlignment().isAligned(false))
4188 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4189 // TODO: if seqs.getSequences().length>1 then should really have warned
4203 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4205 // Pick the tree file
4206 JalviewFileChooser chooser = new JalviewFileChooser(
4207 Cache.getProperty("LAST_DIRECTORY"));
4208 chooser.setFileView(new JalviewFileView());
4209 chooser.setDialogTitle(
4210 MessageManager.getString("label.select_newick_like_tree_file"));
4211 chooser.setToolTipText(
4212 MessageManager.getString("label.load_tree_file"));
4214 chooser.setResponseHandler(0, () -> {
4215 String filePath = chooser.getSelectedFile().getPath();
4216 Cache.setProperty("LAST_DIRECTORY", filePath);
4217 NewickFile fin = null;
4220 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4221 DataSourceType.FILE));
4222 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4223 } catch (Exception ex)
4225 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4226 MessageManager.getString("label.problem_reading_tree_file"),
4227 JvOptionPane.WARNING_MESSAGE);
4228 ex.printStackTrace();
4230 if (fin != null && fin.hasWarningMessage())
4232 JvOptionPane.showMessageDialog(Desktop.desktop,
4233 fin.getWarningMessage(),
4235 .getString("label.possible_problem_with_tree_file"),
4236 JvOptionPane.WARNING_MESSAGE);
4239 chooser.showOpenDialog(this);
4242 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4244 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4247 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4248 int h, int x, int y)
4250 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4254 * Add a treeviewer for the tree extracted from a Newick file object to the
4255 * current alignment view
4262 * Associated alignment input data (or null)
4271 * @return TreePanel handle
4273 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4274 AlignmentView input, int w, int h, int x, int y)
4276 TreePanel tp = null;
4282 if (nf.getTree() != null)
4284 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4290 tp.setLocation(x, y);
4293 Desktop.addInternalFrame(tp, treeTitle, w, h);
4295 } catch (Exception ex)
4297 ex.printStackTrace();
4303 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4306 int w = 400, h = 500;
4310 NewickFile fin = new NewickFile(
4311 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4312 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4313 + (aa.sequenceRef != null
4314 ? (" for " + aa.sequenceRef.getDisplayId(false))
4317 showColumnWiseTree(fin, aa, title, w, h, x, y);
4318 } catch (Throwable xx)
4320 Console.error("Unexpected exception showing tree for contact matrix",
4325 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4326 String treeTitle, int w, int h, int x, int y)
4331 if (nf.getTree() == null)
4335 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4341 tp.setLocation(x, y);
4344 Desktop.addInternalFrame(tp, treeTitle, w, h);
4346 } catch (Throwable xx)
4348 Console.error("Unexpected exception showing tree for contact matrix",
4354 private boolean buildingMenu = false;
4357 * Generates menu items and listener event actions for web service clients
4360 public void BuildWebServiceMenu()
4362 while (buildingMenu)
4367 .errPrintln("Waiting for building menu to finish.");
4369 } catch (Exception e)
4373 final AlignFrame me = this;
4374 buildingMenu = true;
4375 new Thread(new Runnable()
4380 final List<JMenuItem> legacyItems = new ArrayList<>();
4383 // jalview.bin.Console.errPrintln("Building ws menu again "
4384 // + Thread.currentThread());
4385 // TODO: add support for context dependent disabling of services based
4387 // alignment and current selection
4388 // TODO: add additional serviceHandle parameter to specify abstract
4390 // class independently of AbstractName
4391 // TODO: add in rediscovery GUI function to restart discoverer
4392 // TODO: group services by location as well as function and/or
4394 // object broker mechanism.
4395 final Vector<JMenu> wsmenu = new Vector<>();
4396 final IProgressIndicator af = me;
4399 * do not i18n these strings - they are hard-coded in class
4400 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4401 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4403 final JMenu msawsmenu = new JMenu("Alignment");
4404 final JMenu secstrmenu = new JMenu(
4405 "Secondary Structure Prediction");
4406 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4407 final JMenu analymenu = new JMenu("Analysis");
4408 final JMenu dismenu = new JMenu("Protein Disorder");
4409 // JAL-940 - only show secondary structure prediction services from
4410 // the legacy server
4411 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4413 Discoverer.services != null && (Discoverer.services.size() > 0))
4415 // TODO: refactor to allow list of AbstractName/Handler bindings to
4417 // stored or retrieved from elsewhere
4418 // No MSAWS used any more:
4419 // Vector msaws = null; // (Vector)
4420 // Discoverer.services.get("MsaWS");
4421 Vector<ServiceHandle> secstrpr = Discoverer.services
4423 if (secstrpr != null)
4425 // Add any secondary structure prediction services
4426 for (int i = 0, j = secstrpr.size(); i < j; i++)
4428 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4429 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4430 .getServiceClient(sh);
4431 int p = secstrmenu.getItemCount();
4432 impl.attachWSMenuEntry(secstrmenu, me);
4433 int q = secstrmenu.getItemCount();
4434 for (int litm = p; litm < q; litm++)
4436 legacyItems.add(secstrmenu.getItem(litm));
4442 // Add all submenus in the order they should appear on the web
4444 wsmenu.add(msawsmenu);
4445 wsmenu.add(secstrmenu);
4446 wsmenu.add(dismenu);
4447 wsmenu.add(analymenu);
4448 // No search services yet
4449 // wsmenu.add(seqsrchmenu);
4451 javax.swing.SwingUtilities.invokeLater(new Runnable()
4458 webService.removeAll();
4459 // first, add discovered services onto the webservices menu
4460 if (wsmenu.size() > 0)
4462 for (int i = 0, j = wsmenu.size(); i < j; i++)
4464 webService.add(wsmenu.get(i));
4469 webService.add(me.webServiceNoServices);
4471 // TODO: move into separate menu builder class.
4473 // logic for 2.11.1.4 is
4474 // always look to see if there is a discover. if there isn't
4475 // we can't show any Jws2 services
4476 // if there are services available, show them - regardless of
4477 // the 'show JWS2 preference'
4478 // if the discoverer is running then say so
4479 // otherwise offer to trigger discovery if 'show JWS2' is not
4481 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4482 if (jws2servs != null)
4484 if (jws2servs.hasServices())
4486 jws2servs.attachWSMenuEntry(webService, me);
4487 for (Jws2Instance sv : jws2servs.getServices())
4489 if (sv.description.toLowerCase(Locale.ROOT)
4492 for (JMenuItem jmi : legacyItems)
4494 jmi.setVisible(false);
4500 if (jws2servs.isRunning())
4502 JMenuItem tm = new JMenuItem(
4503 "Still discovering JABA Services");
4504 tm.setEnabled(false);
4507 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4509 JMenuItem enableJws2 = new JMenuItem(
4510 "Discover Web Services");
4511 enableJws2.setToolTipText(
4512 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4513 enableJws2.setEnabled(true);
4514 enableJws2.addActionListener(new ActionListener()
4518 public void actionPerformed(ActionEvent e)
4520 // start service discoverer, but ignore preference
4521 Desktop.instance.startServiceDiscovery(false,
4525 webService.add(enableJws2);
4529 build_urlServiceMenu(me.webService);
4530 build_fetchdbmenu(webService);
4531 for (JMenu item : wsmenu)
4533 if (item.getItemCount() == 0)
4535 item.setEnabled(false);
4539 item.setEnabled(true);
4542 } catch (Exception e)
4545 "Exception during web service menu building process.",
4550 } catch (Exception e)
4553 buildingMenu = false;
4560 * construct any groupURL type service menu entries.
4564 protected void build_urlServiceMenu(JMenu webService)
4566 // TODO: remove this code when 2.7 is released
4567 // DEBUG - alignmentView
4569 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4570 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4572 * @Override public void actionPerformed(ActionEvent e) {
4573 * jalview.datamodel.AlignmentView
4574 * .testSelectionViews(af.viewport.getAlignment(),
4575 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4577 * }); webService.add(testAlView);
4579 // TODO: refactor to RestClient discoverer and merge menu entries for
4580 // rest-style services with other types of analysis/calculation service
4581 // SHmmr test client - still being implemented.
4582 // DEBUG - alignmentView
4584 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4587 client.attachWSMenuEntry(
4588 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4594 * Searches the alignment sequences for xRefs and builds the Show
4595 * Cross-References menu (formerly called Show Products), with database
4596 * sources for which cross-references are found (protein sources for a
4597 * nucleotide alignment and vice versa)
4599 * @return true if Show Cross-references menu should be enabled
4601 public boolean canShowProducts()
4603 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4604 AlignmentI dataset = viewport.getAlignment().getDataset();
4606 showProducts.removeAll();
4607 final boolean dna = viewport.getAlignment().isNucleotide();
4609 if (seqs == null || seqs.length == 0)
4611 // nothing to see here.
4615 boolean showp = false;
4618 List<String> ptypes = new CrossRef(seqs, dataset)
4619 .findXrefSourcesForSequences(dna);
4621 for (final String source : ptypes)
4624 final AlignFrame af = this;
4625 JMenuItem xtype = new JMenuItem(source);
4626 xtype.addActionListener(new ActionListener()
4629 public void actionPerformed(ActionEvent e)
4631 showProductsFor(af.viewport.getSequenceSelection(), dna,
4635 showProducts.add(xtype);
4637 showProducts.setVisible(showp);
4638 showProducts.setEnabled(showp);
4639 } catch (Exception e)
4642 "canShowProducts threw an exception - please report to help@jalview.org",
4650 * Finds and displays cross-references for the selected sequences (protein
4651 * products for nucleotide sequences, dna coding sequences for peptides).
4654 * the sequences to show cross-references for
4656 * true if from a nucleotide alignment (so showing proteins)
4658 * the database to show cross-references for
4660 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4661 final String source)
4663 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4668 * Construct and display a new frame containing the translation of this
4669 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4672 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4674 AlignmentI al = null;
4677 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4679 al = dna.translateCdna(codeTable);
4680 } catch (Exception ex)
4682 Console.error("Exception during translation. Please report this !",
4684 final String msg = MessageManager.getString(
4685 "label.error_when_translating_sequences_submit_bug_report");
4686 final String errorTitle = MessageManager
4687 .getString("label.implementation_error")
4688 + MessageManager.getString("label.translation_failed");
4689 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4690 JvOptionPane.ERROR_MESSAGE);
4693 if (al == null || al.getHeight() == 0)
4695 final String msg = MessageManager.getString(
4696 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4697 final String errorTitle = MessageManager
4698 .getString("label.translation_failed");
4699 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4700 JvOptionPane.WARNING_MESSAGE);
4704 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4705 af.setFileFormat(this.currentFileFormat);
4706 final String newTitle = MessageManager
4707 .formatMessage("label.translation_of_params", new Object[]
4708 { this.getTitle(), codeTable.getId() });
4709 af.setTitle(newTitle);
4710 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4712 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4713 viewport.openSplitFrame(af, new Alignment(seqs));
4717 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4724 * Set the file format
4728 public void setFileFormat(FileFormatI format)
4730 this.currentFileFormat = format;
4734 * Try to load a features file onto the alignment.
4737 * contents or path to retrieve file or a File object
4739 * access mode of file (see jalview.io.AlignFile)
4740 * @return true if features file was parsed correctly.
4742 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4745 return avc.parseFeaturesFile(file, sourceType,
4746 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4751 public void refreshFeatureUI(boolean enableIfNecessary)
4753 // note - currently this is only still here rather than in the controller
4754 // because of the featureSettings hard reference that is yet to be
4756 if (enableIfNecessary)
4758 viewport.setShowSequenceFeatures(true);
4759 showSeqFeatures.setSelected(true);
4765 public void dragEnter(DropTargetDragEvent evt)
4770 public void dragExit(DropTargetEvent evt)
4775 public void dragOver(DropTargetDragEvent evt)
4780 public void dropActionChanged(DropTargetDragEvent evt)
4785 public void drop(DropTargetDropEvent evt)
4787 // JAL-1552 - acceptDrop required before getTransferable call for
4788 // Java's Transferable for native dnd
4789 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4790 Transferable t = evt.getTransferable();
4792 final AlignFrame thisaf = this;
4793 final List<Object> files = new ArrayList<>();
4794 List<DataSourceType> protocols = new ArrayList<>();
4798 Desktop.transferFromDropTarget(files, protocols, evt, t);
4799 } catch (Exception e)
4801 e.printStackTrace();
4805 new Thread(new Runnable()
4812 // check to see if any of these files have names matching sequences
4815 SequenceIdMatcher idm = new SequenceIdMatcher(
4816 viewport.getAlignment().getSequencesArray());
4818 * Object[] { String,SequenceI}
4820 ArrayList<Object[]> filesmatched = new ArrayList<>();
4821 ArrayList<Object[]> filesnotmatched = new ArrayList<>();
4822 for (int i = 0; i < files.size(); i++)
4825 Object file = files.get(i);
4826 String fileName = file.toString();
4828 DataSourceType protocol = (file instanceof File
4829 ? DataSourceType.FILE
4830 : FormatAdapter.checkProtocol(fileName));
4831 if (protocol == DataSourceType.FILE)
4834 if (file instanceof File)
4837 Platform.cacheFileData(fl);
4841 fl = new File(fileName);
4843 pdbfn = fl.getName();
4845 else if (protocol == DataSourceType.URL)
4847 URL url = new URL(fileName);
4848 pdbfn = url.getFile();
4850 if (pdbfn.length() > 0)
4852 // attempt to find a match in the alignment
4853 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4854 int l = 0, c = pdbfn.indexOf(".");
4855 while (mtch == null && c != -1)
4860 } while ((c = pdbfn.indexOf(".", l)) > l);
4863 pdbfn = pdbfn.substring(0, l);
4865 mtch = idm.findAllIdMatches(pdbfn);
4867 FileFormatI type = null;
4872 type = new IdentifyFile().identify(file, protocol);
4873 } catch (Exception ex)
4877 if (type != null && type.isStructureFile())
4879 filesmatched.add(new Object[] { file, protocol, mtch });
4883 // File wasn't named like one of the sequences or wasn't a PDB
4885 filesnotmatched.add(new Object[] { file, protocol, type });
4889 if (filesmatched.size() > 0)
4891 boolean autoAssociate = Cache
4892 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4895 String msg = MessageManager.formatMessage(
4896 "label.automatically_associate_structure_files_with_sequences_same_name",
4898 { Integer.valueOf(filesmatched.size())
4900 String ttl = MessageManager.getString(
4901 "label.automatically_associate_structure_files_by_name");
4902 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4903 ttl, JvOptionPane.YES_NO_OPTION);
4904 autoAssociate = choice == JvOptionPane.YES_OPTION;
4908 for (Object[] fm : filesmatched)
4910 // try and associate
4911 // TODO: may want to set a standard ID naming formalism for
4912 // associating PDB files which have no IDs.
4913 for (SequenceI toassoc : (SequenceI[]) fm[2])
4915 PDBEntry pe = new AssociatePdbFileWithSeq()
4916 .associatePdbWithSeq(fm[0].toString(),
4917 (DataSourceType) fm[1], toassoc, false,
4921 jalview.bin.Console.errPrintln("Associated file : "
4922 + (fm[0].toString()) + " with "
4923 + toassoc.getDisplayId(true));
4927 // TODO: do we need to update overview ? only if features are
4929 alignPanel.paintAlignment(true, false);
4935 * add declined structures as sequences
4937 for (Object[] o : filesmatched)
4939 filesnotmatched.add(new Object[] { o[0], o[1] });
4943 if (filesnotmatched.size() > 0)
4945 if (assocfiles > 0 && (Cache.getDefault(
4946 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4947 || JvOptionPane.showConfirmDialog(thisaf,
4948 "<html>" + MessageManager.formatMessage(
4949 "label.ignore_unmatched_dropped_files_info",
4952 filesnotmatched.size())
4955 MessageManager.getString(
4956 "label.ignore_unmatched_dropped_files"),
4957 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4961 for (Object[] fn : filesnotmatched)
4963 loadJalviewDataFile(fn[0], (DataSourceType) fn[1],
4964 (FileFormatI) fn[2], null);
4968 } catch (Exception ex)
4970 ex.printStackTrace();
4978 * Attempt to load a "dropped" file or URL string, by testing in turn for
4980 * <li>an Annotation file</li>
4981 * <li>a JNet file</li>
4982 * <li>a features file</li>
4983 * <li>else try to interpret as an alignment file</li>
4987 * either a filename or a URL string.
4989 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4990 FileFormatI format, SequenceI assocSeq)
4992 // BH 2018 was String file
4995 if (sourceType == null)
4997 sourceType = FormatAdapter.checkProtocol(file);
4999 // if the file isn't identified, or not positively identified as some
5000 // other filetype (PFAM is default unidentified alignment file type) then
5001 // try to parse as annotation.
5002 boolean isAnnotation = (format == null
5003 || FileFormat.Pfam.equals(format))
5004 ? new AnnotationFile().annotateAlignmentView(viewport,
5010 // first see if its a T-COFFEE score file
5011 TCoffeeScoreFile tcf = null;
5014 tcf = new TCoffeeScoreFile(file, sourceType);
5017 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5021 new TCoffeeColourScheme(viewport.getAlignment()));
5022 isAnnotation = true;
5023 setStatus(MessageManager.getString(
5024 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5028 // some problem - if no warning its probable that the ID matching
5029 // process didn't work
5030 JvOptionPane.showMessageDialog(Desktop.desktop,
5031 tcf.getWarningMessage() == null
5032 ? MessageManager.getString(
5033 "label.check_file_matches_sequence_ids_alignment")
5034 : tcf.getWarningMessage(),
5035 MessageManager.getString(
5036 "label.problem_reading_tcoffee_score_file"),
5037 JvOptionPane.WARNING_MESSAGE);
5044 } catch (Exception x)
5047 "Exception when processing data source as T-COFFEE score file",
5053 // try to see if its a JNet 'concise' style annotation file *before*
5055 // try to parse it as a features file
5058 format = new IdentifyFile().identify(file, sourceType);
5060 if (FileFormat.FeatureSettings == format)
5062 if (featureSettings != null)
5064 featureSettings.load(file, sourceType);
5068 FeatureSettings.loadFeatureSettingsFile(getFeatureRenderer(),
5069 fileObject, sourceType);
5072 else if (FileFormat.ScoreMatrix == format)
5074 ScoreMatrixFile sm = new ScoreMatrixFile(
5075 new FileParse(file, sourceType));
5077 // todo: i18n this message
5078 setStatus(MessageManager.formatMessage(
5079 "label.successfully_loaded_matrix",
5080 sm.getMatrixName()));
5082 else if (FileFormat.Jnet.equals(format))
5084 JPredFile predictions = new JPredFile(file, sourceType);
5085 new JnetAnnotationMaker();
5086 JnetAnnotationMaker.add_annotation(predictions,
5087 viewport.getAlignment(), 0, false);
5088 viewport.getAlignment().setupJPredAlignment();
5089 isAnnotation = true;
5091 // else if (IdentifyFile.FeaturesFile.equals(format))
5092 else if (FileFormat.Features.equals(format))
5094 if (parseFeaturesFile(file, sourceType))
5096 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5097 if (splitFrame != null)
5099 splitFrame.repaint();
5103 alignPanel.paintAlignment(true, true);
5109 new FileLoader().LoadFile(viewport, file, sourceType, format);
5116 alignPanel.adjustAnnotationHeight();
5117 viewport.updateSequenceIdColours();
5118 buildSortByAnnotationScoresMenu();
5119 alignPanel.paintAlignment(true, true);
5121 } catch (Exception ex)
5123 ex.printStackTrace();
5124 } catch (OutOfMemoryError oom)
5129 } catch (Exception x)
5134 + (sourceType != null
5135 ? (sourceType == DataSourceType.PASTE
5137 : "using " + sourceType + " from "
5141 ? "(parsing as '" + format + "' file)"
5143 oom, Desktop.desktop);
5148 * Method invoked by the ChangeListener on the tabbed pane, in other words
5149 * when a different tabbed pane is selected by the user or programmatically.
5152 public void tabSelectionChanged(int index)
5157 * update current Overview window title (if there is one)
5158 * to add view name "Original" if necessary
5160 alignPanel.setOverviewTitle(this);
5163 * switch panels and set Overview title (if there is one
5164 * because it was opened automatically)
5166 alignPanel = alignPanels.get(index);
5167 alignPanel.setOverviewTitle(this);
5169 viewport = alignPanel.av;
5170 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5171 setMenusFromViewport(viewport);
5172 if (featureSettings != null && featureSettings.isOpen()
5173 && featureSettings.fr.getViewport() != viewport)
5175 if (viewport.isShowSequenceFeatures())
5177 // refresh the featureSettings to reflect UI change
5178 showFeatureSettingsUI();
5182 // close feature settings for this view.
5183 featureSettings.close();
5190 * 'focus' any colour slider that is open to the selected viewport
5192 if (viewport.getConservationSelected())
5194 SliderPanel.setConservationSlider(alignPanel,
5195 viewport.getResidueShading(), alignPanel.getViewName());
5199 SliderPanel.hideConservationSlider();
5201 if (viewport.getAbovePIDThreshold())
5203 SliderPanel.setPIDSliderSource(alignPanel,
5204 viewport.getResidueShading(), alignPanel.getViewName());
5208 SliderPanel.hidePIDSlider();
5212 * If there is a frame linked to this one in a SplitPane, switch it to the
5213 * same view tab index. No infinite recursion of calls should happen, since
5214 * tabSelectionChanged() should not get invoked on setting the selected
5215 * index to an unchanged value. Guard against setting an invalid index
5216 * before the new view peer tab has been created.
5218 final AlignViewportI peer = viewport.getCodingComplement();
5221 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5222 .getAlignPanel().alignFrame;
5223 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5225 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5231 * On right mouse click on view tab, prompt for and set new view name.
5234 public void tabbedPane_mousePressed(MouseEvent e)
5236 if (e.isPopupTrigger())
5238 String msg = MessageManager.getString("label.enter_view_name");
5239 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5240 String reply = JvOptionPane.showInputDialog(msg, ttl);
5244 viewport.setViewName(reply);
5245 // TODO warn if reply is in getExistingViewNames()?
5246 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5251 public AlignViewport getCurrentView()
5257 * Open the dialog for regex description parsing.
5260 protected void extractScores_actionPerformed(ActionEvent e)
5262 ParseProperties pp = new jalview.analysis.ParseProperties(
5263 viewport.getAlignment());
5264 // TODO: verify regex and introduce GUI dialog for version 2.5
5265 // if (pp.getScoresFromDescription("col", "score column ",
5266 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5268 if (pp.getScoresFromDescription("description column",
5269 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5271 buildSortByAnnotationScoresMenu();
5279 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5283 protected void showDbRefs_actionPerformed(ActionEvent e)
5285 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5291 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5295 protected void showNpFeats_actionPerformed(ActionEvent e)
5297 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5301 * find the viewport amongst the tabs in this alignment frame and close that
5306 public boolean closeView(AlignViewportI av)
5310 this.closeMenuItem_actionPerformed(false);
5313 Component[] comp = tabbedPane.getComponents();
5314 for (int i = 0; comp != null && i < comp.length; i++)
5316 if (comp[i] instanceof AlignmentPanel)
5318 if (((AlignmentPanel) comp[i]).av == av)
5321 closeView((AlignmentPanel) comp[i]);
5329 protected void build_fetchdbmenu(JMenu webService)
5331 // Temporary hack - DBRef Fetcher always top level ws entry.
5332 // TODO We probably want to store a sequence database checklist in
5333 // preferences and have checkboxes.. rather than individual sources selected
5335 final JMenu rfetch = new JMenu(
5336 MessageManager.getString("action.fetch_db_references"));
5337 rfetch.setToolTipText(MessageManager.getString(
5338 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5339 webService.add(rfetch);
5341 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5342 MessageManager.getString("option.trim_retrieved_seqs"));
5343 trimrs.setToolTipText(
5344 MessageManager.getString("label.trim_retrieved_sequences"));
5346 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5347 trimrs.addActionListener(new ActionListener()
5350 public void actionPerformed(ActionEvent e)
5352 trimrs.setSelected(trimrs.isSelected());
5353 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5354 Boolean.valueOf(trimrs.isSelected()).toString());
5358 JMenuItem fetchr = new JMenuItem(
5359 MessageManager.getString("label.standard_databases"));
5360 fetchr.setToolTipText(
5361 MessageManager.getString("label.fetch_embl_uniprot"));
5362 fetchr.addActionListener(new ActionListener()
5366 public void actionPerformed(ActionEvent e)
5368 new Thread(new Runnable()
5373 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5374 .getAlignment().isNucleotide();
5375 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5376 alignPanel.av.getSequenceSelection(),
5377 alignPanel.alignFrame, null,
5378 alignPanel.alignFrame.featureSettings, isNucleotide);
5379 dbRefFetcher.addListener(new FetchFinishedListenerI()
5382 public void finished()
5385 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5386 .getFeatureSettingsModels())
5389 alignPanel.av.mergeFeaturesStyle(srcSettings);
5391 AlignFrame.this.setMenusForViewport();
5394 dbRefFetcher.fetchDBRefs(false);
5402 new Thread(new Runnable()
5407 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5408 .getSequenceFetcherSingleton();
5409 javax.swing.SwingUtilities.invokeLater(new Runnable()
5414 String[] dbclasses = sf.getNonAlignmentSources();
5415 List<DbSourceProxy> otherdb;
5416 JMenu dfetch = new JMenu();
5417 JMenu ifetch = new JMenu();
5418 JMenuItem fetchr = null;
5419 int comp = 0, icomp = 0, mcomp = 15;
5420 String mname = null;
5422 for (String dbclass : dbclasses)
5424 otherdb = sf.getSourceProxy(dbclass);
5425 // add a single entry for this class, or submenu allowing 'fetch
5427 if (otherdb == null || otherdb.size() < 1)
5433 mname = "From " + dbclass;
5435 if (otherdb.size() == 1)
5437 final DbSourceProxy[] dassource = otherdb
5438 .toArray(new DbSourceProxy[0]);
5439 DbSourceProxy src = otherdb.get(0);
5440 fetchr = new JMenuItem(src.getDbSource());
5441 fetchr.addActionListener(new ActionListener()
5445 public void actionPerformed(ActionEvent e)
5447 new Thread(new Runnable()
5453 boolean isNucleotide = alignPanel.alignFrame
5454 .getViewport().getAlignment()
5456 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5457 alignPanel.av.getSequenceSelection(),
5458 alignPanel.alignFrame, dassource,
5459 alignPanel.alignFrame.featureSettings,
5462 .addListener(new FetchFinishedListenerI()
5465 public void finished()
5467 FeatureSettingsModelI srcSettings = dassource[0]
5468 .getFeatureColourScheme();
5469 alignPanel.av.mergeFeaturesStyle(
5471 AlignFrame.this.setMenusForViewport();
5474 dbRefFetcher.fetchDBRefs(false);
5480 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5481 MessageManager.formatMessage(
5482 "label.fetch_retrieve_from", new Object[]
5483 { src.getDbName() })));
5489 final DbSourceProxy[] dassource = otherdb
5490 .toArray(new DbSourceProxy[0]);
5492 DbSourceProxy src = otherdb.get(0);
5493 fetchr = new JMenuItem(MessageManager
5494 .formatMessage("label.fetch_all_param", new Object[]
5495 { src.getDbSource() }));
5496 fetchr.addActionListener(new ActionListener()
5499 public void actionPerformed(ActionEvent e)
5501 new Thread(new Runnable()
5507 boolean isNucleotide = alignPanel.alignFrame
5508 .getViewport().getAlignment()
5510 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5511 alignPanel.av.getSequenceSelection(),
5512 alignPanel.alignFrame, dassource,
5513 alignPanel.alignFrame.featureSettings,
5516 .addListener(new FetchFinishedListenerI()
5519 public void finished()
5521 AlignFrame.this.setMenusForViewport();
5524 dbRefFetcher.fetchDBRefs(false);
5530 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5531 MessageManager.formatMessage(
5532 "label.fetch_retrieve_from_all_sources",
5534 { Integer.valueOf(otherdb.size())
5536 src.getDbSource(), src.getDbName() })));
5539 // and then build the rest of the individual menus
5540 ifetch = new JMenu(MessageManager.formatMessage(
5541 "label.source_from_db_source", new Object[]
5542 { src.getDbSource() }));
5544 String imname = null;
5546 for (DbSourceProxy sproxy : otherdb)
5548 String dbname = sproxy.getDbName();
5549 String sname = dbname.length() > 5
5550 ? dbname.substring(0, 5) + "..."
5552 String msname = dbname.length() > 10
5553 ? dbname.substring(0, 10) + "..."
5557 imname = MessageManager
5558 .formatMessage("label.from_msname", new Object[]
5561 fetchr = new JMenuItem(msname);
5562 final DbSourceProxy[] dassrc = { sproxy };
5563 fetchr.addActionListener(new ActionListener()
5567 public void actionPerformed(ActionEvent e)
5569 new Thread(new Runnable()
5575 boolean isNucleotide = alignPanel.alignFrame
5576 .getViewport().getAlignment()
5578 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5579 alignPanel.av.getSequenceSelection(),
5580 alignPanel.alignFrame, dassrc,
5581 alignPanel.alignFrame.featureSettings,
5584 .addListener(new FetchFinishedListenerI()
5587 public void finished()
5589 AlignFrame.this.setMenusForViewport();
5592 dbRefFetcher.fetchDBRefs(false);
5598 fetchr.setToolTipText(
5599 "<html>" + MessageManager.formatMessage(
5600 "label.fetch_retrieve_from", new Object[]
5604 if (++icomp >= mcomp || i == (otherdb.size()))
5606 ifetch.setText(MessageManager.formatMessage(
5607 "label.source_to_target", imname, sname));
5609 ifetch = new JMenu();
5617 if (comp >= mcomp || dbi >= (dbclasses.length))
5619 dfetch.setText(MessageManager.formatMessage(
5620 "label.source_to_target", mname, dbclass));
5622 dfetch = new JMenu();
5635 * Left justify the whole alignment.
5638 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5640 AlignmentI al = viewport.getAlignment();
5642 viewport.firePropertyChange("alignment", null, al);
5646 * Right justify the whole alignment.
5649 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5651 AlignmentI al = viewport.getAlignment();
5653 viewport.firePropertyChange("alignment", null, al);
5657 public void setShowSeqFeatures(boolean b)
5659 showSeqFeatures.setSelected(b);
5660 viewport.setShowSequenceFeatures(b);
5667 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5668 * awt.event.ActionEvent)
5671 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5673 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5674 alignPanel.paintAlignment(false, false);
5681 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5685 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5687 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5688 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5696 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5697 * .event.ActionEvent)
5700 protected void showGroupConservation_actionPerformed(ActionEvent e)
5702 viewport.setShowGroupConservation(showGroupConservation.getState());
5703 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5710 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5711 * .event.ActionEvent)
5714 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5716 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5717 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5724 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5725 * .event.ActionEvent)
5728 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5730 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5731 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5735 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5737 showSequenceLogo.setState(true);
5738 viewport.setShowSequenceLogo(true);
5739 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5740 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5744 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5746 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5753 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5754 * .event.ActionEvent)
5757 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5759 if (avc.makeGroupsFromSelection())
5761 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5762 alignPanel.updateAnnotation();
5763 alignPanel.paintAlignment(true,
5764 viewport.needToUpdateStructureViews());
5768 public void clearAlignmentSeqRep()
5770 // TODO refactor alignmentseqrep to controller
5771 if (viewport.getAlignment().hasSeqrep())
5773 viewport.getAlignment().setSeqrep(null);
5774 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5775 alignPanel.updateAnnotation();
5776 alignPanel.paintAlignment(true, true);
5781 protected void createGroup_actionPerformed(ActionEvent e)
5783 if (avc.createGroup())
5785 if (applyAutoAnnotationSettings.isSelected())
5787 alignPanel.updateAnnotation(true, false);
5789 alignPanel.alignmentChanged();
5794 protected void unGroup_actionPerformed(ActionEvent e)
5798 alignPanel.alignmentChanged();
5803 * make the given alignmentPanel the currently selected tab
5805 * @param alignmentPanel
5807 public void setDisplayedView(AlignmentPanel alignmentPanel)
5809 if (!viewport.getSequenceSetId()
5810 .equals(alignmentPanel.av.getSequenceSetId()))
5812 throw new Error(MessageManager.getString(
5813 "error.implementation_error_cannot_show_view_alignment_frame"));
5815 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5816 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5818 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5823 * Action on selection of menu options to Show or Hide annotations.
5826 * @param forSequences
5827 * update sequence-related annotations
5828 * @param forAlignment
5829 * update non-sequence-related annotations
5832 public void setAnnotationsVisibility(boolean visible,
5833 boolean forSequences, boolean forAlignment)
5835 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5836 .getAlignmentAnnotation();
5841 for (AlignmentAnnotation aa : anns)
5844 * don't display non-positional annotations on an alignment
5846 if (aa.annotations == null)
5850 boolean apply = (aa.sequenceRef == null && forAlignment)
5851 || (aa.sequenceRef != null && forSequences);
5854 aa.visible = visible;
5857 alignPanel.validateAnnotationDimensions(true);
5858 // TODO this triggers relayout of annotation panel - otherwise annotation
5859 // label height is different to panel height
5860 alignPanel.fontChanged();
5861 alignPanel.alignmentChanged();
5865 * Store selected annotation sort order for the view and repaint.
5868 protected void sortAnnotations_actionPerformed()
5870 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5872 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5873 alignPanel.paintAlignment(false, false);
5878 * @return alignment panels in this alignment frame
5880 public List<? extends AlignmentViewPanel> getAlignPanels()
5882 // alignPanels is never null
5883 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5888 * Open a new alignment window, with the cDNA associated with this (protein)
5889 * alignment, aligned as is the protein.
5891 protected void viewAsCdna_actionPerformed()
5893 // TODO no longer a menu action - refactor as required
5894 final AlignmentI alignment = getViewport().getAlignment();
5895 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5896 if (mappings == null)
5900 List<SequenceI> cdnaSeqs = new ArrayList<>();
5901 for (SequenceI aaSeq : alignment.getSequences())
5903 for (AlignedCodonFrame acf : mappings)
5905 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5909 * There is a cDNA mapping for this protein sequence - add to new
5910 * alignment. It will share the same dataset sequence as other mapped
5911 * cDNA (no new mappings need to be created).
5913 final Sequence newSeq = new Sequence(dnaSeq);
5914 newSeq.setDatasetSequence(dnaSeq);
5915 cdnaSeqs.add(newSeq);
5919 if (cdnaSeqs.size() == 0)
5921 // show a warning dialog no mapped cDNA
5924 AlignmentI cdna = new Alignment(
5925 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5926 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5927 AlignFrame.DEFAULT_HEIGHT);
5928 cdna.alignAs(alignment);
5929 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5931 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5932 AlignFrame.DEFAULT_HEIGHT);
5936 * Set visibility of dna/protein complement view (available when shown in a
5942 protected void showComplement_actionPerformed(boolean show)
5944 SplitContainerI sf = getSplitViewContainer();
5947 sf.setComplementVisible(this, show);
5952 * Generate the reverse (optionally complemented) of the selected sequences,
5953 * and add them to the alignment
5956 protected void showReverse_actionPerformed(boolean complement)
5958 AlignmentI al = null;
5961 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5962 al = dna.reverseCdna(complement);
5963 viewport.addAlignment(al, "");
5964 addHistoryItem(new EditCommand(
5965 MessageManager.getString("label.add_sequences"), Action.PASTE,
5966 al.getSequencesArray(), 0, al.getWidth(),
5967 viewport.getAlignment()));
5968 } catch (Exception ex)
5970 jalview.bin.Console.errPrintln(ex.getMessage());
5976 * Try to run a script in the Groovy console, having first ensured that this
5977 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5978 * be targeted at this alignment.
5981 protected void runGroovy_actionPerformed()
5983 Jalview.getInstance().setCurrentAlignFrame(this);
5984 groovy.console.ui.Console console = Desktop.getGroovyConsole();
5985 if (console != null)
5989 console.setVariable(JalviewObjectI.currentAlFrameName, this);
5990 console.runScript();
5991 } catch (Exception ex)
5993 jalview.bin.Console.errPrintln((ex.toString()));
5994 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5995 MessageManager.getString("label.couldnt_run_groovy_script"),
5996 MessageManager.getString("label.groovy_support_failed"),
5997 JvOptionPane.ERROR_MESSAGE);
6003 .errPrintln("Can't run Groovy script as console not found");
6008 * Hides columns containing (or not containing) a specified feature, provided
6009 * that would not leave all columns hidden
6011 * @param featureType
6012 * @param columnsContaining
6015 public boolean hideFeatureColumns(String featureType,
6016 boolean columnsContaining)
6018 boolean notForHiding = avc.markColumnsContainingFeatures(
6019 columnsContaining, false, false, featureType);
6022 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6023 false, featureType))
6025 getViewport().hideSelectedColumns();
6033 protected void selectHighlightedColumns_actionPerformed(
6034 ActionEvent actionEvent)
6036 // include key modifier check in case user selects from menu
6037 avc.markHighlightedColumns(
6038 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6039 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6040 | ActionEvent.CTRL_MASK)) != 0);
6044 protected void copyHighlightedColumns_actionPerformed(
6045 ActionEvent actionEvent)
6047 avc.copyHighlightedRegionsToClipboard();
6051 * Rebuilds the Colour menu, including any user-defined colours which have
6052 * been loaded either on startup or during the session
6054 public void buildColourMenu()
6056 colourMenu.removeAll();
6058 colourMenu.add(applyToAllGroups);
6059 colourMenu.add(textColour);
6060 colourMenu.addSeparator();
6062 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6063 viewport.getAlignment(), false);
6065 colourMenu.add(annotationColour);
6066 bg.add(annotationColour);
6067 colourMenu.addSeparator();
6068 colourMenu.add(conservationMenuItem);
6069 colourMenu.add(modifyConservation);
6070 colourMenu.add(abovePIDThreshold);
6071 colourMenu.add(modifyPID);
6073 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6074 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6078 * Open a dialog (if not already open) that allows the user to select and
6079 * calculate PCA or Tree analysis
6081 protected void openTreePcaDialog()
6083 if (alignPanel.getCalculationDialog() == null)
6085 new CalculationChooser(AlignFrame.this);
6090 protected void loadVcf_actionPerformed()
6092 JalviewFileChooser chooser = new JalviewFileChooser(
6093 Cache.getProperty("LAST_DIRECTORY"));
6094 chooser.setFileView(new JalviewFileView());
6095 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6096 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6097 final AlignFrame us = this;
6098 chooser.setResponseHandler(0, () -> {
6099 String choice = chooser.getSelectedFile().getPath();
6100 Cache.setProperty("LAST_DIRECTORY", choice);
6101 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6102 new VCFLoader(choice).loadVCF(seqs, us);
6104 chooser.showOpenDialog(null);
6108 private Rectangle lastFeatureSettingsBounds = null;
6111 public void setFeatureSettingsGeometry(Rectangle bounds)
6113 lastFeatureSettingsBounds = bounds;
6117 public Rectangle getFeatureSettingsGeometry()
6119 return lastFeatureSettingsBounds;
6124 class PrintThread extends Thread
6128 public PrintThread(AlignmentPanel ap)
6133 static PageFormat pf;
6138 PrinterJob printJob = PrinterJob.getPrinterJob();
6142 printJob.setPrintable(ap, pf);
6146 printJob.setPrintable(ap);
6149 if (printJob.printDialog())
6154 } catch (Exception PrintException)
6156 PrintException.printStackTrace();