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);
3576 alignPanel.setOverviewPanel(overview);
3577 alignPanel.setOverviewTitle(this);
3579 Desktop.addInternalFrame(frame, overview.getTitle(), true,
3580 frame.getWidth(), frame.getHeight(), true, true);
3582 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3583 final AlignmentPanel thePanel = this.alignPanel;
3584 frame.addInternalFrameListener(
3585 new javax.swing.event.InternalFrameAdapter()
3588 public void internalFrameClosed(
3589 javax.swing.event.InternalFrameEvent evt)
3592 thePanel.setOverviewPanel(null);
3595 if (getKeyListeners().length > 0)
3597 frame.addKeyListener(getKeyListeners()[0]);
3604 public void textColour_actionPerformed()
3606 new TextColourChooser().chooseColour(alignPanel, null);
3610 * public void covariationColour_actionPerformed() {
3612 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3616 public void annotationColour_actionPerformed()
3618 new AnnotationColourChooser(viewport, alignPanel);
3622 public void annotationColumn_actionPerformed(ActionEvent e)
3624 new AnnotationColumnChooser(viewport, alignPanel);
3628 * Action on the user checking or unchecking the option to apply the selected
3629 * colour scheme to all groups. If unchecked, groups may have their own
3630 * independent colour schemes.
3635 public void applyToAllGroups_actionPerformed(boolean selected)
3637 viewport.setColourAppliesToAllGroups(selected);
3641 * Action on user selecting a colour from the colour menu
3644 * the name (not the menu item label!) of the colour scheme
3647 public void changeColour_actionPerformed(String name)
3650 * 'User Defined' opens a panel to configure or load a
3651 * user-defined colour scheme
3653 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3655 new UserDefinedColours(alignPanel);
3660 * otherwise set the chosen colour scheme (or null for 'None')
3662 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3663 viewport, viewport.getAlignment(),
3664 viewport.getHiddenRepSequences());
3669 * Actions on setting or changing the alignment colour scheme
3674 public void changeColour(ColourSchemeI cs)
3676 // TODO: pull up to controller method
3677 ColourMenuHelper.setColourSelected(colourMenu, cs);
3679 viewport.setGlobalColourScheme(cs);
3681 alignPanel.paintAlignment(true, true);
3685 * Show the PID threshold slider panel
3688 protected void modifyPID_actionPerformed()
3690 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3691 alignPanel.getViewName());
3692 SliderPanel.showPIDSlider();
3696 * Show the Conservation slider panel
3699 protected void modifyConservation_actionPerformed()
3701 SliderPanel.setConservationSlider(alignPanel,
3702 viewport.getResidueShading(), alignPanel.getViewName());
3703 SliderPanel.showConservationSlider();
3707 * Action on selecting or deselecting (Colour) By Conservation
3710 public void conservationMenuItem_actionPerformed(boolean selected)
3712 modifyConservation.setEnabled(selected);
3713 viewport.setConservationSelected(selected);
3714 viewport.getResidueShading().setConservationApplied(selected);
3716 changeColour(viewport.getGlobalColourScheme());
3719 modifyConservation_actionPerformed();
3723 SliderPanel.hideConservationSlider();
3728 * Action on selecting or deselecting (Colour) Above PID Threshold
3731 public void abovePIDThreshold_actionPerformed(boolean selected)
3733 modifyPID.setEnabled(selected);
3734 viewport.setAbovePIDThreshold(selected);
3737 viewport.getResidueShading().setThreshold(0,
3738 viewport.isIgnoreGapsConsensus());
3741 changeColour(viewport.getGlobalColourScheme());
3744 modifyPID_actionPerformed();
3748 SliderPanel.hidePIDSlider();
3759 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3761 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3762 AlignmentSorter.sortByPID(viewport.getAlignment(),
3763 viewport.getAlignment().getSequenceAt(0));
3764 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3765 viewport.getAlignment()));
3766 alignPanel.paintAlignment(true, false);
3776 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3778 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3779 AlignmentSorter.sortByID(viewport.getAlignment());
3781 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3782 alignPanel.paintAlignment(true, false);
3792 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3794 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3795 AlignmentSorter.sortByLength(viewport.getAlignment());
3796 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3797 viewport.getAlignment()));
3798 alignPanel.paintAlignment(true, false);
3808 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3810 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3811 AlignmentSorter.sortByGroup(viewport.getAlignment());
3812 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3813 viewport.getAlignment()));
3815 alignPanel.paintAlignment(true, false);
3825 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3827 new RedundancyPanel(alignPanel, this);
3837 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3839 if ((viewport.getSelectionGroup() == null)
3840 || (viewport.getSelectionGroup().getSize() < 2))
3842 JvOptionPane.showInternalMessageDialog(this,
3843 MessageManager.getString(
3844 "label.you_must_select_least_two_sequences"),
3845 MessageManager.getString("label.invalid_selection"),
3846 JvOptionPane.WARNING_MESSAGE);
3850 JInternalFrame frame = new JInternalFrame();
3851 frame.setFrameIcon(null);
3852 frame.setContentPane(new PairwiseAlignPanel(viewport));
3853 Desktop.addInternalFrame(frame,
3854 MessageManager.getString("action.pairwise_alignment"), 600,
3860 public void autoCalculate_actionPerformed(ActionEvent e)
3862 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3863 if (viewport.autoCalculateConsensus)
3865 viewport.firePropertyChange("alignment", null,
3866 viewport.getAlignment().getSequences());
3871 public void sortByTreeOption_actionPerformed(ActionEvent e)
3873 viewport.sortByTree = sortByTree.isSelected();
3877 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3879 viewport.followSelection = listenToViewSelections.isSelected();
3883 * Constructs a tree panel and adds it to the desktop
3886 * tree type (NJ or AV)
3888 * name of score model used to compute the tree
3890 * parameters for the distance or similarity calculation
3892 void newTreePanel(String type, String modelName,
3893 SimilarityParamsI options)
3895 String frameTitle = "";
3898 boolean onSelection = false;
3899 if (viewport.getSelectionGroup() != null
3900 && viewport.getSelectionGroup().getSize() > 0)
3902 SequenceGroup sg = viewport.getSelectionGroup();
3904 /* Decide if the selection is a column region */
3905 for (SequenceI _s : sg.getSequences())
3907 if (_s.getLength() < sg.getEndRes())
3909 JvOptionPane.showMessageDialog(Desktop.desktop,
3910 MessageManager.getString(
3911 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3912 MessageManager.getString(
3913 "label.sequences_selection_not_aligned"),
3914 JvOptionPane.WARNING_MESSAGE);
3923 if (viewport.getAlignment().getHeight() < 2)
3929 tp = new TreePanel(alignPanel, type, modelName, options);
3930 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3932 frameTitle += " from ";
3934 if (viewport.getViewName() != null)
3936 frameTitle += viewport.getViewName() + " of ";
3939 frameTitle += this.title;
3941 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3952 public void addSortByOrderMenuItem(String title,
3953 final AlignmentOrder order)
3955 final JMenuItem item = new JMenuItem(MessageManager
3956 .formatMessage("action.by_title_param", new Object[]
3959 item.addActionListener(new java.awt.event.ActionListener()
3962 public void actionPerformed(ActionEvent e)
3964 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3966 // TODO: JBPNote - have to map order entries to curent SequenceI
3968 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3970 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3971 viewport.getAlignment()));
3973 alignPanel.paintAlignment(true, false);
3979 * Add a new sort by annotation score menu item
3982 * the menu to add the option to
3984 * the label used to retrieve scores for each sequence on the
3987 public void addSortByAnnotScoreMenuItem(JMenu sort,
3988 final String scoreLabel)
3990 final JMenuItem item = new JMenuItem(scoreLabel);
3992 item.addActionListener(new java.awt.event.ActionListener()
3995 public void actionPerformed(ActionEvent e)
3997 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3998 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3999 viewport.getAlignment());// ,viewport.getSelectionGroup());
4000 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
4001 viewport.getAlignment()));
4002 alignPanel.paintAlignment(true, false);
4008 * last hash for alignment's annotation array - used to minimise cost of
4011 protected int _annotationScoreVectorHash;
4014 * search the alignment and rebuild the sort by annotation score submenu the
4015 * last alignment annotation vector hash is stored to minimize cost of
4016 * rebuilding in subsequence calls.
4020 public void buildSortByAnnotationScoresMenu()
4022 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4027 if (viewport.getAlignment().getAlignmentAnnotation()
4028 .hashCode() != _annotationScoreVectorHash)
4030 sortByAnnotScore.removeAll();
4031 // almost certainly a quicker way to do this - but we keep it simple
4032 Hashtable<String, String> scoreSorts = new Hashtable<>();
4033 AlignmentAnnotation aann[];
4034 for (SequenceI sqa : viewport.getAlignment().getSequences())
4036 aann = sqa.getAnnotation();
4037 for (int i = 0; aann != null && i < aann.length; i++)
4039 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4041 scoreSorts.put(aann[i].label, aann[i].label);
4045 Enumeration<String> labels = scoreSorts.keys();
4046 while (labels.hasMoreElements())
4048 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4050 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4053 _annotationScoreVectorHash = viewport.getAlignment()
4054 .getAlignmentAnnotation().hashCode();
4059 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4060 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4061 * call. Listeners are added to remove the menu item when the treePanel is
4062 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4066 public void buildTreeSortMenu()
4068 sortByTreeMenu.removeAll();
4070 List<Component> comps = PaintRefresher.components
4071 .get(viewport.getSequenceSetId());
4072 List<TreePanel> treePanels = new ArrayList<>();
4073 for (Component comp : comps)
4075 if (comp instanceof TreePanel)
4077 treePanels.add((TreePanel) comp);
4081 if (treePanels.size() < 1)
4083 sortByTreeMenu.setVisible(false);
4087 sortByTreeMenu.setVisible(true);
4089 for (final TreePanel tp : treePanels)
4091 final JMenuItem item = new JMenuItem(tp.getTitle());
4092 item.addActionListener(new java.awt.event.ActionListener()
4095 public void actionPerformed(ActionEvent e)
4097 tp.sortByTree_actionPerformed();
4098 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4103 sortByTreeMenu.add(item);
4107 public boolean sortBy(AlignmentOrder alorder, String undoname)
4109 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4110 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4111 if (undoname != null)
4113 addHistoryItem(new OrderCommand(undoname, oldOrder,
4114 viewport.getAlignment()));
4116 alignPanel.paintAlignment(true, false);
4121 * Work out whether the whole set of sequences or just the selected set will
4122 * be submitted for multiple alignment.
4125 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4127 // Now, check we have enough sequences
4128 AlignmentView msa = null;
4130 if ((viewport.getSelectionGroup() != null)
4131 && (viewport.getSelectionGroup().getSize() > 1))
4133 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4134 // some common interface!
4136 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4137 * SequenceI[sz = seqs.getSize(false)];
4139 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4140 * seqs.getSequenceAt(i); }
4142 msa = viewport.getAlignmentView(true);
4144 else if (viewport.getSelectionGroup() != null
4145 && viewport.getSelectionGroup().getSize() == 1)
4147 int option = JvOptionPane.showConfirmDialog(this,
4148 MessageManager.getString("warn.oneseq_msainput_selection"),
4149 MessageManager.getString("label.invalid_selection"),
4150 JvOptionPane.OK_CANCEL_OPTION);
4151 if (option == JvOptionPane.OK_OPTION)
4153 msa = viewport.getAlignmentView(false);
4158 msa = viewport.getAlignmentView(false);
4164 * Decides what is submitted to a secondary structure prediction service: the
4165 * first sequence in the alignment, or in the current selection, or, if the
4166 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4167 * region or the whole alignment. (where the first sequence in the set is the
4168 * one that the prediction will be for).
4170 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4172 AlignmentView seqs = null;
4174 if ((viewport.getSelectionGroup() != null)
4175 && (viewport.getSelectionGroup().getSize() > 0))
4177 seqs = viewport.getAlignmentView(true);
4181 seqs = viewport.getAlignmentView(false);
4183 // limit sequences - JBPNote in future - could spawn multiple prediction
4185 // TODO: viewport.getAlignment().isAligned is a global state - the local
4186 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4187 if (!viewport.getAlignment().isAligned(false))
4189 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4190 // TODO: if seqs.getSequences().length>1 then should really have warned
4204 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4206 // Pick the tree file
4207 JalviewFileChooser chooser = new JalviewFileChooser(
4208 Cache.getProperty("LAST_DIRECTORY"));
4209 chooser.setFileView(new JalviewFileView());
4210 chooser.setDialogTitle(
4211 MessageManager.getString("label.select_newick_like_tree_file"));
4212 chooser.setToolTipText(
4213 MessageManager.getString("label.load_tree_file"));
4215 chooser.setResponseHandler(0, () -> {
4216 String filePath = chooser.getSelectedFile().getPath();
4217 Cache.setProperty("LAST_DIRECTORY", filePath);
4218 NewickFile fin = null;
4221 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4222 DataSourceType.FILE));
4223 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4224 } catch (Exception ex)
4226 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4227 MessageManager.getString("label.problem_reading_tree_file"),
4228 JvOptionPane.WARNING_MESSAGE);
4229 ex.printStackTrace();
4231 if (fin != null && fin.hasWarningMessage())
4233 JvOptionPane.showMessageDialog(Desktop.desktop,
4234 fin.getWarningMessage(),
4236 .getString("label.possible_problem_with_tree_file"),
4237 JvOptionPane.WARNING_MESSAGE);
4240 chooser.showOpenDialog(this);
4243 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4245 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4248 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4249 int h, int x, int y)
4251 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4255 * Add a treeviewer for the tree extracted from a Newick file object to the
4256 * current alignment view
4263 * Associated alignment input data (or null)
4272 * @return TreePanel handle
4274 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4275 AlignmentView input, int w, int h, int x, int y)
4277 TreePanel tp = null;
4283 if (nf.getTree() != null)
4285 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4291 tp.setLocation(x, y);
4294 Desktop.addInternalFrame(tp, treeTitle, w, h);
4296 } catch (Exception ex)
4298 ex.printStackTrace();
4304 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4307 int w = 400, h = 500;
4311 NewickFile fin = new NewickFile(
4312 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4313 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4314 + (aa.sequenceRef != null
4315 ? (" for " + aa.sequenceRef.getDisplayId(false))
4318 showColumnWiseTree(fin, aa, title, w, h, x, y);
4319 } catch (Throwable xx)
4321 Console.error("Unexpected exception showing tree for contact matrix",
4326 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4327 String treeTitle, int w, int h, int x, int y)
4332 if (nf.getTree() == null)
4336 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4342 tp.setLocation(x, y);
4345 Desktop.addInternalFrame(tp, treeTitle, w, h);
4347 } catch (Throwable xx)
4349 Console.error("Unexpected exception showing tree for contact matrix",
4355 private boolean buildingMenu = false;
4358 * Generates menu items and listener event actions for web service clients
4361 public void BuildWebServiceMenu()
4363 while (buildingMenu)
4368 .errPrintln("Waiting for building menu to finish.");
4370 } catch (Exception e)
4374 final AlignFrame me = this;
4375 buildingMenu = true;
4376 new Thread(new Runnable()
4381 final List<JMenuItem> legacyItems = new ArrayList<>();
4384 // jalview.bin.Console.errPrintln("Building ws menu again "
4385 // + Thread.currentThread());
4386 // TODO: add support for context dependent disabling of services based
4388 // alignment and current selection
4389 // TODO: add additional serviceHandle parameter to specify abstract
4391 // class independently of AbstractName
4392 // TODO: add in rediscovery GUI function to restart discoverer
4393 // TODO: group services by location as well as function and/or
4395 // object broker mechanism.
4396 final Vector<JMenu> wsmenu = new Vector<>();
4397 final IProgressIndicator af = me;
4400 * do not i18n these strings - they are hard-coded in class
4401 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4402 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4404 final JMenu msawsmenu = new JMenu("Alignment");
4405 final JMenu secstrmenu = new JMenu(
4406 "Secondary Structure Prediction");
4407 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4408 final JMenu analymenu = new JMenu("Analysis");
4409 final JMenu dismenu = new JMenu("Protein Disorder");
4410 // JAL-940 - only show secondary structure prediction services from
4411 // the legacy server
4412 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4414 Discoverer.services != null && (Discoverer.services.size() > 0))
4416 // TODO: refactor to allow list of AbstractName/Handler bindings to
4418 // stored or retrieved from elsewhere
4419 // No MSAWS used any more:
4420 // Vector msaws = null; // (Vector)
4421 // Discoverer.services.get("MsaWS");
4422 Vector<ServiceHandle> secstrpr = Discoverer.services
4424 if (secstrpr != null)
4426 // Add any secondary structure prediction services
4427 for (int i = 0, j = secstrpr.size(); i < j; i++)
4429 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4430 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4431 .getServiceClient(sh);
4432 int p = secstrmenu.getItemCount();
4433 impl.attachWSMenuEntry(secstrmenu, me);
4434 int q = secstrmenu.getItemCount();
4435 for (int litm = p; litm < q; litm++)
4437 legacyItems.add(secstrmenu.getItem(litm));
4443 // Add all submenus in the order they should appear on the web
4445 wsmenu.add(msawsmenu);
4446 wsmenu.add(secstrmenu);
4447 wsmenu.add(dismenu);
4448 wsmenu.add(analymenu);
4449 // No search services yet
4450 // wsmenu.add(seqsrchmenu);
4452 javax.swing.SwingUtilities.invokeLater(new Runnable()
4459 webService.removeAll();
4460 // first, add discovered services onto the webservices menu
4461 if (wsmenu.size() > 0)
4463 for (int i = 0, j = wsmenu.size(); i < j; i++)
4465 webService.add(wsmenu.get(i));
4470 webService.add(me.webServiceNoServices);
4472 // TODO: move into separate menu builder class.
4474 // logic for 2.11.1.4 is
4475 // always look to see if there is a discover. if there isn't
4476 // we can't show any Jws2 services
4477 // if there are services available, show them - regardless of
4478 // the 'show JWS2 preference'
4479 // if the discoverer is running then say so
4480 // otherwise offer to trigger discovery if 'show JWS2' is not
4482 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4483 if (jws2servs != null)
4485 if (jws2servs.hasServices())
4487 jws2servs.attachWSMenuEntry(webService, me);
4488 for (Jws2Instance sv : jws2servs.getServices())
4490 if (sv.description.toLowerCase(Locale.ROOT)
4493 for (JMenuItem jmi : legacyItems)
4495 jmi.setVisible(false);
4501 if (jws2servs.isRunning())
4503 JMenuItem tm = new JMenuItem(
4504 "Still discovering JABA Services");
4505 tm.setEnabled(false);
4508 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4510 JMenuItem enableJws2 = new JMenuItem(
4511 "Discover Web Services");
4512 enableJws2.setToolTipText(
4513 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4514 enableJws2.setEnabled(true);
4515 enableJws2.addActionListener(new ActionListener()
4519 public void actionPerformed(ActionEvent e)
4521 // start service discoverer, but ignore preference
4522 Desktop.instance.startServiceDiscovery(false,
4526 webService.add(enableJws2);
4530 build_urlServiceMenu(me.webService);
4531 build_fetchdbmenu(webService);
4532 for (JMenu item : wsmenu)
4534 if (item.getItemCount() == 0)
4536 item.setEnabled(false);
4540 item.setEnabled(true);
4543 } catch (Exception e)
4546 "Exception during web service menu building process.",
4551 } catch (Exception e)
4554 buildingMenu = false;
4561 * construct any groupURL type service menu entries.
4565 protected void build_urlServiceMenu(JMenu webService)
4567 // TODO: remove this code when 2.7 is released
4568 // DEBUG - alignmentView
4570 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4571 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4573 * @Override public void actionPerformed(ActionEvent e) {
4574 * jalview.datamodel.AlignmentView
4575 * .testSelectionViews(af.viewport.getAlignment(),
4576 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4578 * }); webService.add(testAlView);
4580 // TODO: refactor to RestClient discoverer and merge menu entries for
4581 // rest-style services with other types of analysis/calculation service
4582 // SHmmr test client - still being implemented.
4583 // DEBUG - alignmentView
4585 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4588 client.attachWSMenuEntry(
4589 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4595 * Searches the alignment sequences for xRefs and builds the Show
4596 * Cross-References menu (formerly called Show Products), with database
4597 * sources for which cross-references are found (protein sources for a
4598 * nucleotide alignment and vice versa)
4600 * @return true if Show Cross-references menu should be enabled
4602 public boolean canShowProducts()
4604 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4605 AlignmentI dataset = viewport.getAlignment().getDataset();
4607 showProducts.removeAll();
4608 final boolean dna = viewport.getAlignment().isNucleotide();
4610 if (seqs == null || seqs.length == 0)
4612 // nothing to see here.
4616 boolean showp = false;
4619 List<String> ptypes = new CrossRef(seqs, dataset)
4620 .findXrefSourcesForSequences(dna);
4622 for (final String source : ptypes)
4625 final AlignFrame af = this;
4626 JMenuItem xtype = new JMenuItem(source);
4627 xtype.addActionListener(new ActionListener()
4630 public void actionPerformed(ActionEvent e)
4632 showProductsFor(af.viewport.getSequenceSelection(), dna,
4636 showProducts.add(xtype);
4638 showProducts.setVisible(showp);
4639 showProducts.setEnabled(showp);
4640 } catch (Exception e)
4643 "canShowProducts threw an exception - please report to help@jalview.org",
4651 * Finds and displays cross-references for the selected sequences (protein
4652 * products for nucleotide sequences, dna coding sequences for peptides).
4655 * the sequences to show cross-references for
4657 * true if from a nucleotide alignment (so showing proteins)
4659 * the database to show cross-references for
4661 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4662 final String source)
4664 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4669 * Construct and display a new frame containing the translation of this
4670 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4673 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4675 AlignmentI al = null;
4678 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4680 al = dna.translateCdna(codeTable);
4681 } catch (Exception ex)
4683 Console.error("Exception during translation. Please report this !",
4685 final String msg = MessageManager.getString(
4686 "label.error_when_translating_sequences_submit_bug_report");
4687 final String errorTitle = MessageManager
4688 .getString("label.implementation_error")
4689 + MessageManager.getString("label.translation_failed");
4690 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4691 JvOptionPane.ERROR_MESSAGE);
4694 if (al == null || al.getHeight() == 0)
4696 final String msg = MessageManager.getString(
4697 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4698 final String errorTitle = MessageManager
4699 .getString("label.translation_failed");
4700 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4701 JvOptionPane.WARNING_MESSAGE);
4705 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4706 af.setFileFormat(this.currentFileFormat);
4707 final String newTitle = MessageManager
4708 .formatMessage("label.translation_of_params", new Object[]
4709 { this.getTitle(), codeTable.getId() });
4710 af.setTitle(newTitle);
4711 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4713 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4714 viewport.openSplitFrame(af, new Alignment(seqs));
4718 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4725 * Set the file format
4729 public void setFileFormat(FileFormatI format)
4731 this.currentFileFormat = format;
4735 * Try to load a features file onto the alignment.
4738 * contents or path to retrieve file or a File object
4740 * access mode of file (see jalview.io.AlignFile)
4741 * @return true if features file was parsed correctly.
4743 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4746 return avc.parseFeaturesFile(file, sourceType,
4747 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4752 public void refreshFeatureUI(boolean enableIfNecessary)
4754 // note - currently this is only still here rather than in the controller
4755 // because of the featureSettings hard reference that is yet to be
4757 if (enableIfNecessary)
4759 viewport.setShowSequenceFeatures(true);
4760 showSeqFeatures.setSelected(true);
4766 public void dragEnter(DropTargetDragEvent evt)
4771 public void dragExit(DropTargetEvent evt)
4776 public void dragOver(DropTargetDragEvent evt)
4781 public void dropActionChanged(DropTargetDragEvent evt)
4786 public void drop(DropTargetDropEvent evt)
4788 // JAL-1552 - acceptDrop required before getTransferable call for
4789 // Java's Transferable for native dnd
4790 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4791 Transferable t = evt.getTransferable();
4793 final AlignFrame thisaf = this;
4794 final List<Object> files = new ArrayList<>();
4795 List<DataSourceType> protocols = new ArrayList<>();
4799 Desktop.transferFromDropTarget(files, protocols, evt, t);
4800 } catch (Exception e)
4802 e.printStackTrace();
4806 new Thread(new Runnable()
4813 // check to see if any of these files have names matching sequences
4816 SequenceIdMatcher idm = new SequenceIdMatcher(
4817 viewport.getAlignment().getSequencesArray());
4819 * Object[] { String,SequenceI}
4821 ArrayList<Object[]> filesmatched = new ArrayList<>();
4822 ArrayList<Object[]> filesnotmatched = new ArrayList<>();
4823 for (int i = 0; i < files.size(); i++)
4826 Object file = files.get(i);
4827 String fileName = file.toString();
4829 DataSourceType protocol = (file instanceof File
4830 ? DataSourceType.FILE
4831 : FormatAdapter.checkProtocol(fileName));
4832 if (protocol == DataSourceType.FILE)
4835 if (file instanceof File)
4838 Platform.cacheFileData(fl);
4842 fl = new File(fileName);
4844 pdbfn = fl.getName();
4846 else if (protocol == DataSourceType.URL)
4848 URL url = new URL(fileName);
4849 pdbfn = url.getFile();
4851 if (pdbfn.length() > 0)
4853 // attempt to find a match in the alignment
4854 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4855 int l = 0, c = pdbfn.indexOf(".");
4856 while (mtch == null && c != -1)
4861 } while ((c = pdbfn.indexOf(".", l)) > l);
4864 pdbfn = pdbfn.substring(0, l);
4866 mtch = idm.findAllIdMatches(pdbfn);
4868 FileFormatI type = null;
4873 type = new IdentifyFile().identify(file, protocol);
4874 } catch (Exception ex)
4878 if (type != null && type.isStructureFile())
4880 filesmatched.add(new Object[] { file, protocol, mtch });
4884 // File wasn't named like one of the sequences or wasn't a PDB
4886 filesnotmatched.add(new Object[] { file, protocol, type });
4890 if (filesmatched.size() > 0)
4892 boolean autoAssociate = Cache
4893 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4896 String msg = MessageManager.formatMessage(
4897 "label.automatically_associate_structure_files_with_sequences_same_name",
4899 { Integer.valueOf(filesmatched.size())
4901 String ttl = MessageManager.getString(
4902 "label.automatically_associate_structure_files_by_name");
4903 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4904 ttl, JvOptionPane.YES_NO_OPTION);
4905 autoAssociate = choice == JvOptionPane.YES_OPTION;
4909 for (Object[] fm : filesmatched)
4911 // try and associate
4912 // TODO: may want to set a standard ID naming formalism for
4913 // associating PDB files which have no IDs.
4914 for (SequenceI toassoc : (SequenceI[]) fm[2])
4916 PDBEntry pe = new AssociatePdbFileWithSeq()
4917 .associatePdbWithSeq(fm[0].toString(),
4918 (DataSourceType) fm[1], toassoc, false,
4922 jalview.bin.Console.errPrintln("Associated file : "
4923 + (fm[0].toString()) + " with "
4924 + toassoc.getDisplayId(true));
4928 // TODO: do we need to update overview ? only if features are
4930 alignPanel.paintAlignment(true, false);
4936 * add declined structures as sequences
4938 for (Object[] o : filesmatched)
4940 filesnotmatched.add(new Object[] { o[0], o[1] });
4944 if (filesnotmatched.size() > 0)
4946 if (assocfiles > 0 && (Cache.getDefault(
4947 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4948 || JvOptionPane.showConfirmDialog(thisaf,
4949 "<html>" + MessageManager.formatMessage(
4950 "label.ignore_unmatched_dropped_files_info",
4953 filesnotmatched.size())
4956 MessageManager.getString(
4957 "label.ignore_unmatched_dropped_files"),
4958 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4962 for (Object[] fn : filesnotmatched)
4964 loadJalviewDataFile(fn[0], (DataSourceType) fn[1],
4965 (FileFormatI) fn[2], null);
4969 } catch (Exception ex)
4971 ex.printStackTrace();
4979 * Attempt to load a "dropped" file or URL string, by testing in turn for
4981 * <li>an Annotation file</li>
4982 * <li>a JNet file</li>
4983 * <li>a features file</li>
4984 * <li>else try to interpret as an alignment file</li>
4988 * either a filename or a URL string.
4990 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4991 FileFormatI format, SequenceI assocSeq)
4993 // BH 2018 was String file
4996 if (sourceType == null)
4998 sourceType = FormatAdapter.checkProtocol(file);
5000 // if the file isn't identified, or not positively identified as some
5001 // other filetype (PFAM is default unidentified alignment file type) then
5002 // try to parse as annotation.
5003 boolean isAnnotation = (format == null
5004 || FileFormat.Pfam.equals(format))
5005 ? new AnnotationFile().annotateAlignmentView(viewport,
5011 // first see if its a T-COFFEE score file
5012 TCoffeeScoreFile tcf = null;
5015 tcf = new TCoffeeScoreFile(file, sourceType);
5018 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5022 new TCoffeeColourScheme(viewport.getAlignment()));
5023 isAnnotation = true;
5024 setStatus(MessageManager.getString(
5025 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5029 // some problem - if no warning its probable that the ID matching
5030 // process didn't work
5031 JvOptionPane.showMessageDialog(Desktop.desktop,
5032 tcf.getWarningMessage() == null
5033 ? MessageManager.getString(
5034 "label.check_file_matches_sequence_ids_alignment")
5035 : tcf.getWarningMessage(),
5036 MessageManager.getString(
5037 "label.problem_reading_tcoffee_score_file"),
5038 JvOptionPane.WARNING_MESSAGE);
5045 } catch (Exception x)
5048 "Exception when processing data source as T-COFFEE score file",
5054 // try to see if its a JNet 'concise' style annotation file *before*
5056 // try to parse it as a features file
5059 format = new IdentifyFile().identify(file, sourceType);
5061 if (FileFormat.FeatureSettings == format)
5063 if (featureSettings != null)
5065 featureSettings.load(file, sourceType);
5069 FeatureSettings.loadFeatureSettingsFile(getFeatureRenderer(),
5070 fileObject, sourceType);
5073 else if (FileFormat.ScoreMatrix == format)
5075 ScoreMatrixFile sm = new ScoreMatrixFile(
5076 new FileParse(file, sourceType));
5078 // todo: i18n this message
5079 setStatus(MessageManager.formatMessage(
5080 "label.successfully_loaded_matrix",
5081 sm.getMatrixName()));
5083 else if (FileFormat.Jnet.equals(format))
5085 JPredFile predictions = new JPredFile(file, sourceType);
5086 new JnetAnnotationMaker();
5087 JnetAnnotationMaker.add_annotation(predictions,
5088 viewport.getAlignment(), 0, false);
5089 viewport.getAlignment().setupJPredAlignment();
5090 isAnnotation = true;
5092 // else if (IdentifyFile.FeaturesFile.equals(format))
5093 else if (FileFormat.Features.equals(format))
5095 if (parseFeaturesFile(file, sourceType))
5097 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5098 if (splitFrame != null)
5100 splitFrame.repaint();
5104 alignPanel.paintAlignment(true, true);
5110 new FileLoader().LoadFile(viewport, file, sourceType, format);
5117 alignPanel.adjustAnnotationHeight();
5118 viewport.updateSequenceIdColours();
5119 buildSortByAnnotationScoresMenu();
5120 alignPanel.paintAlignment(true, true);
5122 } catch (Exception ex)
5124 ex.printStackTrace();
5125 } catch (OutOfMemoryError oom)
5130 } catch (Exception x)
5135 + (sourceType != null
5136 ? (sourceType == DataSourceType.PASTE
5138 : "using " + sourceType + " from "
5142 ? "(parsing as '" + format + "' file)"
5144 oom, Desktop.desktop);
5149 * Method invoked by the ChangeListener on the tabbed pane, in other words
5150 * when a different tabbed pane is selected by the user or programmatically.
5153 public void tabSelectionChanged(int index)
5158 * update current Overview window title (if there is one)
5159 * to add view name "Original" if necessary
5161 alignPanel.setOverviewTitle(this);
5164 * switch panels and set Overview title (if there is one
5165 * because it was opened automatically)
5167 alignPanel = alignPanels.get(index);
5168 alignPanel.setOverviewTitle(this);
5170 viewport = alignPanel.av;
5171 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5172 setMenusFromViewport(viewport);
5173 if (featureSettings != null && featureSettings.isOpen()
5174 && featureSettings.fr.getViewport() != viewport)
5176 if (viewport.isShowSequenceFeatures())
5178 // refresh the featureSettings to reflect UI change
5179 showFeatureSettingsUI();
5183 // close feature settings for this view.
5184 featureSettings.close();
5191 * 'focus' any colour slider that is open to the selected viewport
5193 if (viewport.getConservationSelected())
5195 SliderPanel.setConservationSlider(alignPanel,
5196 viewport.getResidueShading(), alignPanel.getViewName());
5200 SliderPanel.hideConservationSlider();
5202 if (viewport.getAbovePIDThreshold())
5204 SliderPanel.setPIDSliderSource(alignPanel,
5205 viewport.getResidueShading(), alignPanel.getViewName());
5209 SliderPanel.hidePIDSlider();
5213 * If there is a frame linked to this one in a SplitPane, switch it to the
5214 * same view tab index. No infinite recursion of calls should happen, since
5215 * tabSelectionChanged() should not get invoked on setting the selected
5216 * index to an unchanged value. Guard against setting an invalid index
5217 * before the new view peer tab has been created.
5219 final AlignViewportI peer = viewport.getCodingComplement();
5222 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5223 .getAlignPanel().alignFrame;
5224 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5226 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5232 * On right mouse click on view tab, prompt for and set new view name.
5235 public void tabbedPane_mousePressed(MouseEvent e)
5237 if (e.isPopupTrigger())
5239 String msg = MessageManager.getString("label.enter_view_name");
5240 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5241 String reply = JvOptionPane.showInputDialog(msg, ttl);
5245 viewport.setViewName(reply);
5246 // TODO warn if reply is in getExistingViewNames()?
5247 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5252 public AlignViewport getCurrentView()
5258 * Open the dialog for regex description parsing.
5261 protected void extractScores_actionPerformed(ActionEvent e)
5263 ParseProperties pp = new jalview.analysis.ParseProperties(
5264 viewport.getAlignment());
5265 // TODO: verify regex and introduce GUI dialog for version 2.5
5266 // if (pp.getScoresFromDescription("col", "score column ",
5267 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5269 if (pp.getScoresFromDescription("description column",
5270 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5272 buildSortByAnnotationScoresMenu();
5280 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5284 protected void showDbRefs_actionPerformed(ActionEvent e)
5286 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5292 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5296 protected void showNpFeats_actionPerformed(ActionEvent e)
5298 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5302 * find the viewport amongst the tabs in this alignment frame and close that
5307 public boolean closeView(AlignViewportI av)
5311 this.closeMenuItem_actionPerformed(false);
5314 Component[] comp = tabbedPane.getComponents();
5315 for (int i = 0; comp != null && i < comp.length; i++)
5317 if (comp[i] instanceof AlignmentPanel)
5319 if (((AlignmentPanel) comp[i]).av == av)
5322 closeView((AlignmentPanel) comp[i]);
5330 protected void build_fetchdbmenu(JMenu webService)
5332 // Temporary hack - DBRef Fetcher always top level ws entry.
5333 // TODO We probably want to store a sequence database checklist in
5334 // preferences and have checkboxes.. rather than individual sources selected
5336 final JMenu rfetch = new JMenu(
5337 MessageManager.getString("action.fetch_db_references"));
5338 rfetch.setToolTipText(MessageManager.getString(
5339 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5340 webService.add(rfetch);
5342 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5343 MessageManager.getString("option.trim_retrieved_seqs"));
5344 trimrs.setToolTipText(
5345 MessageManager.getString("label.trim_retrieved_sequences"));
5347 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5348 trimrs.addActionListener(new ActionListener()
5351 public void actionPerformed(ActionEvent e)
5353 trimrs.setSelected(trimrs.isSelected());
5354 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5355 Boolean.valueOf(trimrs.isSelected()).toString());
5359 JMenuItem fetchr = new JMenuItem(
5360 MessageManager.getString("label.standard_databases"));
5361 fetchr.setToolTipText(
5362 MessageManager.getString("label.fetch_embl_uniprot"));
5363 fetchr.addActionListener(new ActionListener()
5367 public void actionPerformed(ActionEvent e)
5369 new Thread(new Runnable()
5374 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5375 .getAlignment().isNucleotide();
5376 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5377 alignPanel.av.getSequenceSelection(),
5378 alignPanel.alignFrame, null,
5379 alignPanel.alignFrame.featureSettings, isNucleotide);
5380 dbRefFetcher.addListener(new FetchFinishedListenerI()
5383 public void finished()
5386 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5387 .getFeatureSettingsModels())
5390 alignPanel.av.mergeFeaturesStyle(srcSettings);
5392 AlignFrame.this.setMenusForViewport();
5395 dbRefFetcher.fetchDBRefs(false);
5403 new Thread(new Runnable()
5408 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5409 .getSequenceFetcherSingleton();
5410 javax.swing.SwingUtilities.invokeLater(new Runnable()
5415 String[] dbclasses = sf.getNonAlignmentSources();
5416 List<DbSourceProxy> otherdb;
5417 JMenu dfetch = new JMenu();
5418 JMenu ifetch = new JMenu();
5419 JMenuItem fetchr = null;
5420 int comp = 0, icomp = 0, mcomp = 15;
5421 String mname = null;
5423 for (String dbclass : dbclasses)
5425 otherdb = sf.getSourceProxy(dbclass);
5426 // add a single entry for this class, or submenu allowing 'fetch
5428 if (otherdb == null || otherdb.size() < 1)
5434 mname = "From " + dbclass;
5436 if (otherdb.size() == 1)
5438 final DbSourceProxy[] dassource = otherdb
5439 .toArray(new DbSourceProxy[0]);
5440 DbSourceProxy src = otherdb.get(0);
5441 fetchr = new JMenuItem(src.getDbSource());
5442 fetchr.addActionListener(new ActionListener()
5446 public void actionPerformed(ActionEvent e)
5448 new Thread(new Runnable()
5454 boolean isNucleotide = alignPanel.alignFrame
5455 .getViewport().getAlignment()
5457 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5458 alignPanel.av.getSequenceSelection(),
5459 alignPanel.alignFrame, dassource,
5460 alignPanel.alignFrame.featureSettings,
5463 .addListener(new FetchFinishedListenerI()
5466 public void finished()
5468 FeatureSettingsModelI srcSettings = dassource[0]
5469 .getFeatureColourScheme();
5470 alignPanel.av.mergeFeaturesStyle(
5472 AlignFrame.this.setMenusForViewport();
5475 dbRefFetcher.fetchDBRefs(false);
5481 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5482 MessageManager.formatMessage(
5483 "label.fetch_retrieve_from", new Object[]
5484 { src.getDbName() })));
5490 final DbSourceProxy[] dassource = otherdb
5491 .toArray(new DbSourceProxy[0]);
5493 DbSourceProxy src = otherdb.get(0);
5494 fetchr = new JMenuItem(MessageManager
5495 .formatMessage("label.fetch_all_param", new Object[]
5496 { src.getDbSource() }));
5497 fetchr.addActionListener(new ActionListener()
5500 public void actionPerformed(ActionEvent e)
5502 new Thread(new Runnable()
5508 boolean isNucleotide = alignPanel.alignFrame
5509 .getViewport().getAlignment()
5511 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5512 alignPanel.av.getSequenceSelection(),
5513 alignPanel.alignFrame, dassource,
5514 alignPanel.alignFrame.featureSettings,
5517 .addListener(new FetchFinishedListenerI()
5520 public void finished()
5522 AlignFrame.this.setMenusForViewport();
5525 dbRefFetcher.fetchDBRefs(false);
5531 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5532 MessageManager.formatMessage(
5533 "label.fetch_retrieve_from_all_sources",
5535 { Integer.valueOf(otherdb.size())
5537 src.getDbSource(), src.getDbName() })));
5540 // and then build the rest of the individual menus
5541 ifetch = new JMenu(MessageManager.formatMessage(
5542 "label.source_from_db_source", new Object[]
5543 { src.getDbSource() }));
5545 String imname = null;
5547 for (DbSourceProxy sproxy : otherdb)
5549 String dbname = sproxy.getDbName();
5550 String sname = dbname.length() > 5
5551 ? dbname.substring(0, 5) + "..."
5553 String msname = dbname.length() > 10
5554 ? dbname.substring(0, 10) + "..."
5558 imname = MessageManager
5559 .formatMessage("label.from_msname", new Object[]
5562 fetchr = new JMenuItem(msname);
5563 final DbSourceProxy[] dassrc = { sproxy };
5564 fetchr.addActionListener(new ActionListener()
5568 public void actionPerformed(ActionEvent e)
5570 new Thread(new Runnable()
5576 boolean isNucleotide = alignPanel.alignFrame
5577 .getViewport().getAlignment()
5579 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5580 alignPanel.av.getSequenceSelection(),
5581 alignPanel.alignFrame, dassrc,
5582 alignPanel.alignFrame.featureSettings,
5585 .addListener(new FetchFinishedListenerI()
5588 public void finished()
5590 AlignFrame.this.setMenusForViewport();
5593 dbRefFetcher.fetchDBRefs(false);
5599 fetchr.setToolTipText(
5600 "<html>" + MessageManager.formatMessage(
5601 "label.fetch_retrieve_from", new Object[]
5605 if (++icomp >= mcomp || i == (otherdb.size()))
5607 ifetch.setText(MessageManager.formatMessage(
5608 "label.source_to_target", imname, sname));
5610 ifetch = new JMenu();
5618 if (comp >= mcomp || dbi >= (dbclasses.length))
5620 dfetch.setText(MessageManager.formatMessage(
5621 "label.source_to_target", mname, dbclass));
5623 dfetch = new JMenu();
5636 * Left justify the whole alignment.
5639 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5641 AlignmentI al = viewport.getAlignment();
5643 viewport.firePropertyChange("alignment", null, al);
5647 * Right justify the whole alignment.
5650 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5652 AlignmentI al = viewport.getAlignment();
5654 viewport.firePropertyChange("alignment", null, al);
5658 public void setShowSeqFeatures(boolean b)
5660 showSeqFeatures.setSelected(b);
5661 viewport.setShowSequenceFeatures(b);
5668 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5669 * awt.event.ActionEvent)
5672 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5674 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5675 alignPanel.paintAlignment(false, false);
5682 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5686 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5688 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5689 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5697 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5698 * .event.ActionEvent)
5701 protected void showGroupConservation_actionPerformed(ActionEvent e)
5703 viewport.setShowGroupConservation(showGroupConservation.getState());
5704 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5711 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5712 * .event.ActionEvent)
5715 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5717 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5718 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5725 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5726 * .event.ActionEvent)
5729 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5731 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5732 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5736 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5738 showSequenceLogo.setState(true);
5739 viewport.setShowSequenceLogo(true);
5740 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5741 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5745 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5747 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5754 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5755 * .event.ActionEvent)
5758 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5760 if (avc.makeGroupsFromSelection())
5762 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5763 alignPanel.updateAnnotation();
5764 alignPanel.paintAlignment(true,
5765 viewport.needToUpdateStructureViews());
5769 public void clearAlignmentSeqRep()
5771 // TODO refactor alignmentseqrep to controller
5772 if (viewport.getAlignment().hasSeqrep())
5774 viewport.getAlignment().setSeqrep(null);
5775 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5776 alignPanel.updateAnnotation();
5777 alignPanel.paintAlignment(true, true);
5782 protected void createGroup_actionPerformed(ActionEvent e)
5784 if (avc.createGroup())
5786 if (applyAutoAnnotationSettings.isSelected())
5788 alignPanel.updateAnnotation(true, false);
5790 alignPanel.alignmentChanged();
5795 protected void unGroup_actionPerformed(ActionEvent e)
5799 alignPanel.alignmentChanged();
5804 * make the given alignmentPanel the currently selected tab
5806 * @param alignmentPanel
5808 public void setDisplayedView(AlignmentPanel alignmentPanel)
5810 if (!viewport.getSequenceSetId()
5811 .equals(alignmentPanel.av.getSequenceSetId()))
5813 throw new Error(MessageManager.getString(
5814 "error.implementation_error_cannot_show_view_alignment_frame"));
5816 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5817 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5819 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5824 * Action on selection of menu options to Show or Hide annotations.
5827 * @param forSequences
5828 * update sequence-related annotations
5829 * @param forAlignment
5830 * update non-sequence-related annotations
5833 public void setAnnotationsVisibility(boolean visible,
5834 boolean forSequences, boolean forAlignment)
5836 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5837 .getAlignmentAnnotation();
5842 for (AlignmentAnnotation aa : anns)
5845 * don't display non-positional annotations on an alignment
5847 if (aa.annotations == null)
5851 boolean apply = (aa.sequenceRef == null && forAlignment)
5852 || (aa.sequenceRef != null && forSequences);
5855 aa.visible = visible;
5858 alignPanel.validateAnnotationDimensions(true);
5859 // TODO this triggers relayout of annotation panel - otherwise annotation
5860 // label height is different to panel height
5861 alignPanel.fontChanged();
5862 alignPanel.alignmentChanged();
5866 * Store selected annotation sort order for the view and repaint.
5869 protected void sortAnnotations_actionPerformed()
5871 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5873 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5874 alignPanel.paintAlignment(false, false);
5879 * @return alignment panels in this alignment frame
5881 public List<? extends AlignmentViewPanel> getAlignPanels()
5883 // alignPanels is never null
5884 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5889 * Open a new alignment window, with the cDNA associated with this (protein)
5890 * alignment, aligned as is the protein.
5892 protected void viewAsCdna_actionPerformed()
5894 // TODO no longer a menu action - refactor as required
5895 final AlignmentI alignment = getViewport().getAlignment();
5896 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5897 if (mappings == null)
5901 List<SequenceI> cdnaSeqs = new ArrayList<>();
5902 for (SequenceI aaSeq : alignment.getSequences())
5904 for (AlignedCodonFrame acf : mappings)
5906 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5910 * There is a cDNA mapping for this protein sequence - add to new
5911 * alignment. It will share the same dataset sequence as other mapped
5912 * cDNA (no new mappings need to be created).
5914 final Sequence newSeq = new Sequence(dnaSeq);
5915 newSeq.setDatasetSequence(dnaSeq);
5916 cdnaSeqs.add(newSeq);
5920 if (cdnaSeqs.size() == 0)
5922 // show a warning dialog no mapped cDNA
5925 AlignmentI cdna = new Alignment(
5926 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5927 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5928 AlignFrame.DEFAULT_HEIGHT);
5929 cdna.alignAs(alignment);
5930 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5932 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5933 AlignFrame.DEFAULT_HEIGHT);
5937 * Set visibility of dna/protein complement view (available when shown in a
5943 protected void showComplement_actionPerformed(boolean show)
5945 SplitContainerI sf = getSplitViewContainer();
5948 sf.setComplementVisible(this, show);
5953 * Generate the reverse (optionally complemented) of the selected sequences,
5954 * and add them to the alignment
5957 protected void showReverse_actionPerformed(boolean complement)
5959 AlignmentI al = null;
5962 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5963 al = dna.reverseCdna(complement);
5964 viewport.addAlignment(al, "");
5965 addHistoryItem(new EditCommand(
5966 MessageManager.getString("label.add_sequences"), Action.PASTE,
5967 al.getSequencesArray(), 0, al.getWidth(),
5968 viewport.getAlignment()));
5969 } catch (Exception ex)
5971 jalview.bin.Console.errPrintln(ex.getMessage());
5977 * Try to run a script in the Groovy console, having first ensured that this
5978 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5979 * be targeted at this alignment.
5982 protected void runGroovy_actionPerformed()
5984 Jalview.getInstance().setCurrentAlignFrame(this);
5985 groovy.console.ui.Console console = Desktop.getGroovyConsole();
5986 if (console != null)
5990 console.setVariable(JalviewObjectI.currentAlFrameName, this);
5991 console.runScript();
5992 } catch (Exception ex)
5994 jalview.bin.Console.errPrintln((ex.toString()));
5995 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5996 MessageManager.getString("label.couldnt_run_groovy_script"),
5997 MessageManager.getString("label.groovy_support_failed"),
5998 JvOptionPane.ERROR_MESSAGE);
6004 .errPrintln("Can't run Groovy script as console not found");
6009 * Hides columns containing (or not containing) a specified feature, provided
6010 * that would not leave all columns hidden
6012 * @param featureType
6013 * @param columnsContaining
6016 public boolean hideFeatureColumns(String featureType,
6017 boolean columnsContaining)
6019 boolean notForHiding = avc.markColumnsContainingFeatures(
6020 columnsContaining, false, false, featureType);
6023 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6024 false, featureType))
6026 getViewport().hideSelectedColumns();
6034 protected void selectHighlightedColumns_actionPerformed(
6035 ActionEvent actionEvent)
6037 // include key modifier check in case user selects from menu
6038 avc.markHighlightedColumns(
6039 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6040 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6041 | ActionEvent.CTRL_MASK)) != 0);
6045 protected void copyHighlightedColumns_actionPerformed(
6046 ActionEvent actionEvent)
6048 avc.copyHighlightedRegionsToClipboard();
6052 * Rebuilds the Colour menu, including any user-defined colours which have
6053 * been loaded either on startup or during the session
6055 public void buildColourMenu()
6057 colourMenu.removeAll();
6059 colourMenu.add(applyToAllGroups);
6060 colourMenu.add(textColour);
6061 colourMenu.addSeparator();
6063 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6064 viewport.getAlignment(), false);
6066 colourMenu.add(annotationColour);
6067 bg.add(annotationColour);
6068 colourMenu.addSeparator();
6069 colourMenu.add(conservationMenuItem);
6070 colourMenu.add(modifyConservation);
6071 colourMenu.add(abovePIDThreshold);
6072 colourMenu.add(modifyPID);
6074 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6075 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6079 * Open a dialog (if not already open) that allows the user to select and
6080 * calculate PCA or Tree analysis
6082 protected void openTreePcaDialog()
6084 if (alignPanel.getCalculationDialog() == null)
6086 new CalculationChooser(AlignFrame.this);
6091 protected void loadVcf_actionPerformed()
6093 JalviewFileChooser chooser = new JalviewFileChooser(
6094 Cache.getProperty("LAST_DIRECTORY"));
6095 chooser.setFileView(new JalviewFileView());
6096 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6097 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6098 final AlignFrame us = this;
6099 chooser.setResponseHandler(0, () -> {
6100 String choice = chooser.getSelectedFile().getPath();
6101 Cache.setProperty("LAST_DIRECTORY", choice);
6102 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6103 new VCFLoader(choice).loadVCF(seqs, us);
6105 chooser.showOpenDialog(null);
6109 private Rectangle lastFeatureSettingsBounds = null;
6112 public void setFeatureSettingsGeometry(Rectangle bounds)
6114 lastFeatureSettingsBounds = bounds;
6118 public Rectangle getFeatureSettingsGeometry()
6120 return lastFeatureSettingsBounds;
6125 class PrintThread extends Thread
6129 public PrintThread(AlignmentPanel ap)
6134 static PageFormat pf;
6139 PrinterJob printJob = PrinterJob.getPrinterJob();
6143 printJob.setPrintable(ap, pf);
6147 printJob.setPrintable(ap);
6150 if (printJob.printDialog())
6155 } catch (Exception PrintException)
6157 PrintException.printStackTrace();