2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Rectangle;
27 import java.awt.Toolkit;
28 import java.awt.datatransfer.Clipboard;
29 import java.awt.datatransfer.DataFlavor;
30 import java.awt.datatransfer.StringSelection;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.dnd.DnDConstants;
33 import java.awt.dnd.DropTargetDragEvent;
34 import java.awt.dnd.DropTargetDropEvent;
35 import java.awt.dnd.DropTargetEvent;
36 import java.awt.dnd.DropTargetListener;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.awt.print.PageFormat;
47 import java.awt.print.PrinterJob;
48 import java.beans.PropertyChangeEvent;
50 import java.io.FileWriter;
51 import java.io.IOException;
52 import java.io.PrintWriter;
54 import java.util.ArrayList;
55 import java.util.Arrays;
56 import java.util.Deque;
57 import java.util.Enumeration;
58 import java.util.Hashtable;
59 import java.util.List;
60 import java.util.Locale;
61 import java.util.Vector;
63 import javax.swing.ButtonGroup;
64 import javax.swing.JCheckBoxMenuItem;
65 import javax.swing.JComponent;
66 import javax.swing.JEditorPane;
67 import javax.swing.JInternalFrame;
68 import javax.swing.JLabel;
69 import javax.swing.JLayeredPane;
70 import javax.swing.JMenu;
71 import javax.swing.JMenuItem;
72 import javax.swing.JPanel;
73 import javax.swing.JScrollPane;
74 import javax.swing.SwingUtilities;
76 import ext.vamsas.ServiceHandle;
77 import jalview.analysis.AlignmentSorter;
78 import jalview.analysis.AlignmentUtils;
79 import jalview.analysis.CrossRef;
80 import jalview.analysis.Dna;
81 import jalview.analysis.GeneticCodeI;
82 import jalview.analysis.ParseProperties;
83 import jalview.analysis.SequenceIdMatcher;
84 import jalview.api.AlignExportSettingsI;
85 import jalview.api.AlignViewControllerGuiI;
86 import jalview.api.AlignViewControllerI;
87 import jalview.api.AlignViewportI;
88 import jalview.api.AlignmentViewPanel;
89 import jalview.api.FeatureSettingsControllerI;
90 import jalview.api.FeatureSettingsModelI;
91 import jalview.api.SplitContainerI;
92 import jalview.api.ViewStyleI;
93 import jalview.api.analysis.SimilarityParamsI;
94 import jalview.bin.Cache;
95 import jalview.bin.Console;
96 import jalview.bin.Jalview;
97 import jalview.commands.CommandI;
98 import jalview.commands.EditCommand;
99 import jalview.commands.EditCommand.Action;
100 import jalview.commands.OrderCommand;
101 import jalview.commands.RemoveGapColCommand;
102 import jalview.commands.RemoveGapsCommand;
103 import jalview.commands.SlideSequencesCommand;
104 import jalview.commands.TrimRegionCommand;
105 import jalview.datamodel.AlignExportSettingsAdapter;
106 import jalview.datamodel.AlignedCodonFrame;
107 import jalview.datamodel.Alignment;
108 import jalview.datamodel.AlignmentAnnotation;
109 import jalview.datamodel.AlignmentExportData;
110 import jalview.datamodel.AlignmentI;
111 import jalview.datamodel.AlignmentOrder;
112 import jalview.datamodel.AlignmentView;
113 import jalview.datamodel.ColumnSelection;
114 import jalview.datamodel.ContactMatrixI;
115 import jalview.datamodel.HiddenColumns;
116 import jalview.datamodel.PDBEntry;
117 import jalview.datamodel.SeqCigar;
118 import jalview.datamodel.Sequence;
119 import jalview.datamodel.SequenceGroup;
120 import jalview.datamodel.SequenceI;
121 import jalview.gui.ColourMenuHelper.ColourChangeListener;
122 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
123 import jalview.io.AlignmentProperties;
124 import jalview.io.AnnotationFile;
125 import jalview.io.BackupFiles;
126 import jalview.io.BioJsHTMLOutput;
127 import jalview.io.DataSourceType;
128 import jalview.io.FileFormat;
129 import jalview.io.FileFormatI;
130 import jalview.io.FileFormats;
131 import jalview.io.FileLoader;
132 import jalview.io.FileParse;
133 import jalview.io.FormatAdapter;
134 import jalview.io.HtmlSvgOutput;
135 import jalview.io.IdentifyFile;
136 import jalview.io.JPredFile;
137 import jalview.io.JalviewFileChooser;
138 import jalview.io.JalviewFileView;
139 import jalview.io.JnetAnnotationMaker;
140 import jalview.io.NewickFile;
141 import jalview.io.ScoreMatrixFile;
142 import jalview.io.TCoffeeScoreFile;
143 import jalview.io.exceptions.ImageOutputException;
144 import jalview.io.vcf.VCFLoader;
145 import jalview.jbgui.GAlignFrame;
146 import jalview.project.Jalview2XML;
147 import jalview.schemes.ColourSchemeI;
148 import jalview.schemes.ColourSchemes;
149 import jalview.schemes.ResidueColourScheme;
150 import jalview.schemes.TCoffeeColourScheme;
151 import jalview.util.HttpUtils;
152 import jalview.util.ImageMaker.TYPE;
153 import jalview.util.MessageManager;
154 import jalview.util.Platform;
155 import jalview.util.imagemaker.BitmapImageSizing;
156 import jalview.viewmodel.AlignmentViewport;
157 import jalview.viewmodel.ViewportRanges;
158 import jalview.ws.DBRefFetcher;
159 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
160 import jalview.ws.jws1.Discoverer;
161 import jalview.ws.jws2.Jws2Discoverer;
162 import jalview.ws.jws2.jabaws2.Jws2Instance;
163 import jalview.ws.seqfetcher.DbSourceProxy;
169 * @version $Revision$
171 @SuppressWarnings("serial")
172 public class AlignFrame extends GAlignFrame implements DropTargetListener,
173 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
176 public static final int DEFAULT_WIDTH = 700;
178 public static final int DEFAULT_HEIGHT = 500;
181 * The currently displayed panel (selected tabbed view if more than one)
183 public AlignmentPanel alignPanel;
185 AlignViewport viewport;
187 public AlignViewControllerI avc;
189 List<AlignmentPanel> alignPanels = new ArrayList<>();
192 * Last format used to load or save alignments in this window
194 FileFormatI currentFileFormat = null;
197 * Current filename for this alignment
199 String fileName = null;
204 * Creates a new AlignFrame object with specific width and height.
210 public AlignFrame(AlignmentI al, int width, int height)
212 this(al, null, width, height);
216 * Creates a new AlignFrame object with specific width, height and
222 * @param sequenceSetId
224 public AlignFrame(AlignmentI al, int width, int height,
225 String sequenceSetId)
227 this(al, null, width, height, sequenceSetId);
231 * Creates a new AlignFrame object with specific width, height and
237 * @param sequenceSetId
240 public AlignFrame(AlignmentI al, int width, int height,
241 String sequenceSetId, String viewId)
243 this(al, null, width, height, sequenceSetId, viewId);
247 * new alignment window with hidden columns
251 * @param hiddenColumns
252 * ColumnSelection or null
254 * Width of alignment frame
258 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
261 this(al, hiddenColumns, width, height, null);
265 * Create alignment frame for al with hiddenColumns, a specific width and
266 * height, and specific sequenceId
269 * @param hiddenColumns
272 * @param sequenceSetId
275 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
276 int height, String sequenceSetId)
278 this(al, hiddenColumns, width, height, sequenceSetId, null);
282 * Create alignment frame for al with hiddenColumns, a specific width and
283 * height, and specific sequenceId
286 * @param hiddenColumns
289 * @param sequenceSetId
294 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
295 int height, String sequenceSetId, String viewId)
297 setSize(width, height);
299 if (al.getDataset() == null)
304 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
306 alignPanel = new AlignmentPanel(this, viewport);
308 addAlignmentPanel(alignPanel, true);
312 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
313 HiddenColumns hiddenColumns, int width, int height)
315 setSize(width, height);
317 if (al.getDataset() == null)
322 viewport = new AlignViewport(al, hiddenColumns);
324 if (hiddenSeqs != null && hiddenSeqs.length > 0)
326 viewport.hideSequence(hiddenSeqs);
328 alignPanel = new AlignmentPanel(this, viewport);
329 addAlignmentPanel(alignPanel, true);
334 * Make a new AlignFrame from existing alignmentPanels
341 public AlignFrame(AlignmentPanel ap)
345 addAlignmentPanel(ap, false);
350 * initalise the alignframe from the underlying viewport data and the
357 // setBackground(Color.white); // BH 2019
359 if (!Jalview.isHeadlessMode())
361 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
364 avc = new jalview.controller.AlignViewController(this, viewport,
366 if (viewport.getAlignmentConservationAnnotation() == null)
368 // BLOSUM62Colour.setEnabled(false);
369 conservationMenuItem.setEnabled(false);
370 modifyConservation.setEnabled(false);
371 // PIDColour.setEnabled(false);
372 // abovePIDThreshold.setEnabled(false);
373 // modifyPID.setEnabled(false);
376 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
378 if (sortby.equals("Id"))
380 sortIDMenuItem_actionPerformed(null);
382 else if (sortby.equals("Pairwise Identity"))
384 sortPairwiseMenuItem_actionPerformed(null);
388 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
390 setMenusFromViewport(viewport);
391 buildSortByAnnotationScoresMenu();
392 calculateTree.addActionListener(new ActionListener()
396 public void actionPerformed(ActionEvent e)
403 if (Desktop.desktop != null)
405 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
406 if (!Platform.isJS())
408 addServiceListeners();
413 if (viewport.getWrapAlignment())
415 wrapMenuItem_actionPerformed(null);
418 if (Cache.getDefault("SHOW_OVERVIEW", false))
420 this.overviewMenuItem_actionPerformed(null);
425 final List<AlignmentViewPanel> selviews = new ArrayList<>();
426 final List<AlignmentPanel> origview = new ArrayList<>();
427 final String menuLabel = MessageManager
428 .getString("label.copy_format_from");
429 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
430 new ViewSetProvider()
434 public AlignmentPanel[] getAllAlignmentPanels()
437 origview.add(alignPanel);
438 // make an array of all alignment panels except for this one
439 List<AlignmentPanel> aps = new ArrayList<>(
440 Arrays.asList(Desktop.getAlignmentPanels(null)));
441 aps.remove(AlignFrame.this.alignPanel);
442 return aps.toArray(new AlignmentPanel[aps.size()]);
444 }, selviews, new ItemListener()
448 public void itemStateChanged(ItemEvent e)
450 if (origview.size() > 0)
452 final AlignmentPanel ap = origview.get(0);
455 * Copy the ViewStyle of the selected panel to 'this one'.
456 * Don't change value of 'scaleProteinAsCdna' unless copying
459 ViewStyleI vs = selviews.get(0).getAlignViewport()
461 boolean fromSplitFrame = selviews.get(0)
462 .getAlignViewport().getCodingComplement() != null;
465 vs.setScaleProteinAsCdna(ap.getAlignViewport()
466 .getViewStyle().isScaleProteinAsCdna());
468 ap.getAlignViewport().setViewStyle(vs);
471 * Also rescale ViewStyle of SplitFrame complement if there is
472 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
473 * the whole ViewStyle (allow cDNA protein to have different
476 AlignViewportI complement = ap.getAlignViewport()
477 .getCodingComplement();
478 if (complement != null && vs.isScaleProteinAsCdna())
480 AlignFrame af = Desktop.getAlignFrameFor(complement);
481 ((SplitFrame) af.getSplitViewContainer())
483 af.setMenusForViewport();
487 ap.setSelected(true);
488 ap.alignFrame.setMenusForViewport();
493 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
494 .indexOf("devel") > -1
495 || Cache.getDefault("VERSION", "DEVELOPMENT")
496 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
498 formatMenu.add(vsel);
500 addFocusListener(new FocusAdapter()
503 public void focusGained(FocusEvent e)
505 Jalview.setCurrentAlignFrame(AlignFrame.this);
512 * Change the filename and format for the alignment, and enable the 'reload'
513 * button functionality.
520 public void setFileName(String file, FileFormatI format)
523 setFileFormat(format);
524 reload.setEnabled(true);
528 * JavaScript will have this, maybe others. More dependable than a file name
529 * and maintains a reference to the actual bytes loaded.
533 public void setFileObject(File file)
535 this.fileObject = file;
539 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
542 void addKeyListener()
544 addKeyListener(new KeyAdapter()
547 public void keyPressed(KeyEvent evt)
549 if (viewport.cursorMode
550 && ((evt.getKeyCode() >= KeyEvent.VK_0
551 && evt.getKeyCode() <= KeyEvent.VK_9)
552 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
553 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
554 && Character.isDigit(evt.getKeyChar()))
556 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
559 switch (evt.getKeyCode())
562 case 27: // escape key
563 deselectAllSequenceMenuItem_actionPerformed(null);
567 case KeyEvent.VK_DOWN:
568 if (evt.isAltDown() || !viewport.cursorMode)
570 moveSelectedSequences(false);
572 if (viewport.cursorMode)
574 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
579 if (evt.isAltDown() || !viewport.cursorMode)
581 moveSelectedSequences(true);
583 if (viewport.cursorMode)
585 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
590 case KeyEvent.VK_LEFT:
591 if (evt.isAltDown() || !viewport.cursorMode)
593 slideSequences(false,
594 alignPanel.getSeqPanel().getKeyboardNo1());
598 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
603 case KeyEvent.VK_RIGHT:
604 if (evt.isAltDown() || !viewport.cursorMode)
606 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
610 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
614 case KeyEvent.VK_SPACE:
615 if (viewport.cursorMode)
617 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
618 || evt.isShiftDown() || evt.isAltDown());
622 // case KeyEvent.VK_A:
623 // if (viewport.cursorMode)
625 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
626 // //System.out.println("A");
630 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
631 * System.out.println("closing bracket"); } break;
633 case KeyEvent.VK_DELETE:
634 case KeyEvent.VK_BACK_SPACE:
635 if (!viewport.cursorMode)
637 cut_actionPerformed();
641 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
642 || evt.isShiftDown() || evt.isAltDown());
648 if (viewport.cursorMode)
650 alignPanel.getSeqPanel().setCursorRow();
654 if (viewport.cursorMode && !evt.isControlDown())
656 alignPanel.getSeqPanel().setCursorColumn();
660 if (viewport.cursorMode)
662 alignPanel.getSeqPanel().setCursorPosition();
666 case KeyEvent.VK_ENTER:
667 case KeyEvent.VK_COMMA:
668 if (viewport.cursorMode)
670 alignPanel.getSeqPanel().setCursorRowAndColumn();
675 if (viewport.cursorMode)
677 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
681 if (viewport.cursorMode)
683 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
688 viewport.cursorMode = !viewport.cursorMode;
689 setStatus(MessageManager
690 .formatMessage("label.keyboard_editing_mode", new String[]
691 { (viewport.cursorMode ? "on" : "off") }));
692 if (viewport.cursorMode)
694 ViewportRanges ranges = viewport.getRanges();
695 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
697 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
700 alignPanel.getSeqPanel().seqCanvas.repaint();
706 Help.showHelpWindow();
707 } catch (Exception ex)
709 ex.printStackTrace();
714 boolean toggleSeqs = !evt.isControlDown();
715 boolean toggleCols = !evt.isShiftDown();
716 toggleHiddenRegions(toggleSeqs, toggleCols);
721 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
722 boolean modifyExisting = true; // always modify, don't clear
723 // evt.isShiftDown();
724 boolean invertHighlighted = evt.isAltDown();
725 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
729 case KeyEvent.VK_PAGE_UP:
730 viewport.getRanges().pageUp();
732 case KeyEvent.VK_PAGE_DOWN:
733 viewport.getRanges().pageDown();
739 public void keyReleased(KeyEvent evt)
741 switch (evt.getKeyCode())
743 case KeyEvent.VK_LEFT:
744 if (evt.isAltDown() || !viewport.cursorMode)
746 viewport.firePropertyChange("alignment", null,
747 viewport.getAlignment().getSequences());
751 case KeyEvent.VK_RIGHT:
752 if (evt.isAltDown() || !viewport.cursorMode)
754 viewport.firePropertyChange("alignment", null,
755 viewport.getAlignment().getSequences());
763 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
765 ap.alignFrame = this;
766 avc = new jalview.controller.AlignViewController(this, viewport,
771 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
773 int aSize = alignPanels.size();
775 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
777 if (aSize == 1 && ap.av.getViewName() == null)
779 this.getContentPane().add(ap, BorderLayout.CENTER);
785 setInitialTabVisible();
788 expandViews.setEnabled(true);
789 gatherViews.setEnabled(true);
790 tabbedPane.addTab(ap.av.getViewName(), ap);
792 ap.setVisible(false);
797 if (ap.av.isPadGaps())
799 ap.av.getAlignment().padGaps();
801 ap.av.updateConservation(ap);
802 ap.av.updateConsensus(ap);
803 ap.av.updateStrucConsensus(ap);
807 public void setInitialTabVisible()
809 expandViews.setEnabled(true);
810 gatherViews.setEnabled(true);
811 tabbedPane.setVisible(true);
812 AlignmentPanel first = alignPanels.get(0);
813 tabbedPane.addTab(first.av.getViewName(), first);
814 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
817 public AlignViewport getViewport()
822 /* Set up intrinsic listeners for dynamically generated GUI bits. */
823 private void addServiceListeners()
825 final java.beans.PropertyChangeListener thisListener;
826 Desktop.instance.addJalviewPropertyChangeListener("services",
827 thisListener = new java.beans.PropertyChangeListener()
830 public void propertyChange(PropertyChangeEvent evt)
832 // // System.out.println("Discoverer property change.");
833 // if (evt.getPropertyName().equals("services"))
835 SwingUtilities.invokeLater(new Runnable()
842 "Rebuild WS Menu for service change");
843 BuildWebServiceMenu();
850 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
853 public void internalFrameClosed(
854 javax.swing.event.InternalFrameEvent evt)
856 // System.out.println("deregistering discoverer listener");
857 Desktop.instance.removeJalviewPropertyChangeListener("services",
859 closeMenuItem_actionPerformed(true);
862 // Finally, build the menu once to get current service state
863 new Thread(new Runnable()
868 BuildWebServiceMenu();
874 * Configure menu items that vary according to whether the alignment is
875 * nucleotide or protein
877 public void setGUINucleotide()
879 AlignmentI al = getViewport().getAlignment();
880 boolean nucleotide = al.isNucleotide();
882 loadVcf.setVisible(nucleotide);
883 showTranslation.setVisible(nucleotide);
884 showReverse.setVisible(nucleotide);
885 showReverseComplement.setVisible(nucleotide);
886 conservationMenuItem.setEnabled(!nucleotide);
888 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
889 showGroupConservation.setEnabled(!nucleotide);
891 showComplementMenuItem
892 .setText(nucleotide ? MessageManager.getString("label.protein")
893 : MessageManager.getString("label.nucleotide"));
897 * set up menus for the current viewport. This may be called after any
898 * operation that affects the data in the current view (selection changed,
899 * etc) to update the menus to reflect the new state.
902 public void setMenusForViewport()
904 setMenusFromViewport(viewport);
908 * Need to call this method when tabs are selected for multiple views, or when
909 * loading from Jalview2XML.java
914 public void setMenusFromViewport(AlignViewport av)
916 padGapsMenuitem.setSelected(av.isPadGaps());
917 colourTextMenuItem.setSelected(av.isShowColourText());
918 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
919 modifyPID.setEnabled(abovePIDThreshold.isSelected());
920 conservationMenuItem.setSelected(av.getConservationSelected());
921 modifyConservation.setEnabled(conservationMenuItem.isSelected());
922 seqLimits.setSelected(av.getShowJVSuffix());
923 idRightAlign.setSelected(av.isRightAlignIds());
924 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
925 renderGapsMenuItem.setSelected(av.isRenderGaps());
926 wrapMenuItem.setSelected(av.getWrapAlignment());
927 scaleAbove.setVisible(av.getWrapAlignment());
928 scaleLeft.setVisible(av.getWrapAlignment());
929 scaleRight.setVisible(av.getWrapAlignment());
930 annotationPanelMenuItem.setState(av.isShowAnnotation());
932 * Show/hide annotations only enabled if annotation panel is shown
934 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
935 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
936 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
937 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
938 viewBoxesMenuItem.setSelected(av.getShowBoxes());
939 viewTextMenuItem.setSelected(av.getShowText());
940 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
941 showGroupConsensus.setSelected(av.isShowGroupConsensus());
942 showGroupConservation.setSelected(av.isShowGroupConservation());
943 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
944 showSequenceLogo.setSelected(av.isShowSequenceLogo());
945 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
947 ColourMenuHelper.setColourSelected(colourMenu,
948 av.getGlobalColourScheme());
950 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
951 hiddenMarkers.setState(av.getShowHiddenMarkers());
952 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
953 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
954 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
955 autoCalculate.setSelected(av.autoCalculateConsensus);
956 sortByTree.setSelected(av.sortByTree);
957 listenToViewSelections.setSelected(av.followSelection);
959 showProducts.setEnabled(canShowProducts());
960 setGroovyEnabled(Desktop.getGroovyConsole() != null);
966 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
970 public void setGroovyEnabled(boolean b)
972 runGroovy.setEnabled(b);
975 private IProgressIndicator progressBar;
980 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
983 public void setProgressBar(String message, long id)
985 if (!Platform.isHeadless() && progressBar != null)
986 progressBar.setProgressBar(message, id);
990 public void registerHandler(final long id,
991 final IProgressIndicatorHandler handler)
993 if (progressBar != null)
994 progressBar.registerHandler(id, handler);
999 * @return true if any progress bars are still active
1002 public boolean operationInProgress()
1004 return progressBar == null ? false : progressBar.operationInProgress();
1008 * Sets the text of the status bar. Note that setting a null or empty value
1009 * will cause the status bar to be hidden, with possibly undesirable flicker
1010 * of the screen layout.
1013 public void setStatus(String text)
1015 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1019 * Added so Castor Mapping file can obtain Jalview Version
1021 public String getVersion()
1023 return Cache.getProperty("VERSION");
1026 public FeatureRenderer getFeatureRenderer()
1028 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1032 public void fetchSequence_actionPerformed()
1034 new SequenceFetcher(this);
1038 public void addFromFile_actionPerformed(ActionEvent e)
1040 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1044 public void reload_actionPerformed(ActionEvent e)
1046 if (fileName != null)
1048 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1049 // originating file's format
1050 // TODO: work out how to recover feature settings for correct view(s) when
1051 // file is reloaded.
1052 if (FileFormat.Jalview.equals(currentFileFormat))
1054 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1055 for (int i = 0; i < frames.length; i++)
1057 if (frames[i] instanceof AlignFrame && frames[i] != this
1058 && ((AlignFrame) frames[i]).fileName != null
1059 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1063 frames[i].setSelected(true);
1064 Desktop.instance.closeAssociatedWindows();
1065 } catch (java.beans.PropertyVetoException ex)
1071 Desktop.instance.closeAssociatedWindows();
1073 FileLoader loader = new FileLoader();
1074 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1075 ? DataSourceType.URL
1076 : DataSourceType.FILE;
1077 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1081 Rectangle bounds = this.getBounds();
1083 FileLoader loader = new FileLoader();
1085 AlignFrame newframe = null;
1087 if (fileObject == null)
1090 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1091 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1092 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1097 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1098 DataSourceType.FILE, currentFileFormat);
1101 newframe.setBounds(bounds);
1102 if (featureSettings != null && featureSettings.isShowing())
1104 final Rectangle fspos = featureSettings.frame.getBounds();
1105 // TODO: need a 'show feature settings' function that takes bounds -
1106 // need to refactor Desktop.addFrame
1107 newframe.featureSettings_actionPerformed(null);
1108 final FeatureSettings nfs = newframe.featureSettings;
1109 SwingUtilities.invokeLater(new Runnable()
1114 nfs.frame.setBounds(fspos);
1117 this.featureSettings.close();
1118 this.featureSettings = null;
1120 this.closeMenuItem_actionPerformed(true);
1126 public void addFromText_actionPerformed(ActionEvent e)
1129 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1133 public void addFromURL_actionPerformed(ActionEvent e)
1135 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1139 public void save_actionPerformed(ActionEvent e)
1141 if (fileName == null || (currentFileFormat == null)
1142 || HttpUtils.startsWithHttpOrHttps(fileName))
1144 saveAs_actionPerformed();
1148 saveAlignment(fileName, currentFileFormat);
1153 * Saves the alignment to a file with a name chosen by the user, if necessary
1154 * warning if a file would be overwritten
1157 public void saveAs_actionPerformed()
1159 String format = currentFileFormat == null ? null
1160 : currentFileFormat.getName();
1161 JalviewFileChooser chooser = JalviewFileChooser
1162 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1164 chooser.setFileView(new JalviewFileView());
1165 chooser.setDialogTitle(
1166 MessageManager.getString("label.save_alignment_to_file"));
1167 chooser.setToolTipText(MessageManager.getString("action.save"));
1169 int value = chooser.showSaveDialog(this);
1171 if (value != JalviewFileChooser.APPROVE_OPTION)
1175 currentFileFormat = chooser.getSelectedFormat();
1176 // todo is this (2005) test now obsolete - value is never null?
1177 while (currentFileFormat == null)
1179 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1181 .getString("label.select_file_format_before_saving"),
1182 MessageManager.getString("label.file_format_not_specified"),
1183 JvOptionPane.WARNING_MESSAGE);
1184 currentFileFormat = chooser.getSelectedFormat();
1185 value = chooser.showSaveDialog(this);
1186 if (value != JalviewFileChooser.APPROVE_OPTION)
1192 fileName = chooser.getSelectedFile().getPath();
1194 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1195 Cache.setProperty("LAST_DIRECTORY", fileName);
1196 saveAlignment(fileName, currentFileFormat);
1199 boolean lastSaveSuccessful = false;
1201 FileFormatI lastFormatSaved;
1203 String lastFilenameSaved;
1206 * Raise a dialog or status message for the last call to saveAlignment.
1208 * @return true if last call to saveAlignment(file, format) was successful.
1210 public boolean isSaveAlignmentSuccessful()
1213 if (!lastSaveSuccessful)
1215 if (!Platform.isHeadless())
1217 JvOptionPane.showInternalMessageDialog(this, MessageManager
1218 .formatMessage("label.couldnt_save_file", new Object[]
1219 { lastFilenameSaved }),
1220 MessageManager.getString("label.error_saving_file"),
1221 JvOptionPane.WARNING_MESSAGE);
1225 Console.error(MessageManager
1226 .formatMessage("label.couldnt_save_file", new Object[]
1227 { lastFilenameSaved }));
1233 setStatus(MessageManager.formatMessage(
1234 "label.successfully_saved_to_file_in_format", new Object[]
1235 { lastFilenameSaved, lastFormatSaved }));
1238 return lastSaveSuccessful;
1242 * Saves the alignment to the specified file path, in the specified format,
1243 * which may be an alignment format, or Jalview project format. If the
1244 * alignment has hidden regions, or the format is one capable of including
1245 * non-sequence data (features, annotations, groups), then the user may be
1246 * prompted to specify what to include in the output.
1251 public void saveAlignment(String file, FileFormatI format)
1253 lastSaveSuccessful = true;
1254 lastFilenameSaved = file;
1255 lastFormatSaved = format;
1257 if (FileFormat.Jalview.equals(format))
1259 String shortName = title;
1260 if (shortName.indexOf(File.separatorChar) > -1)
1262 shortName = shortName
1263 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1265 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1268 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1269 if (lastSaveSuccessful)
1271 this.getViewport().setSavedUpToDate(true);
1274 statusBar.setText(MessageManager.formatMessage(
1275 "label.successfully_saved_to_file_in_format", new Object[]
1281 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1282 Runnable cancelAction = () -> {
1283 lastSaveSuccessful = false;
1285 Runnable outputAction = () -> {
1286 // todo defer this to inside formatSequences (or later)
1287 AlignmentExportData exportData = viewport.getAlignExportData(options);
1288 String output = new FormatAdapter(alignPanel, options)
1289 .formatSequences(format, exportData.getAlignment(),
1290 exportData.getOmitHidden(),
1291 exportData.getStartEndPostions(),
1292 viewport.getAlignment().getHiddenColumns());
1295 lastSaveSuccessful = false;
1299 // create backupfiles object and get new temp filename destination
1300 boolean doBackup = BackupFiles.getEnabled();
1301 BackupFiles backupfiles = null;
1304 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1305 backupfiles = new BackupFiles(file);
1309 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1311 Console.trace("ALIGNFRAME setting PrintWriter");
1312 PrintWriter out = new PrintWriter(new FileWriter(tempFilePath));
1314 if (backupfiles != null)
1316 Console.trace("ALIGNFRAME about to write to temp file "
1317 + backupfiles.getTempFilePath());
1321 Console.trace("ALIGNFRAME about to close file");
1323 Console.trace("ALIGNFRAME closed file");
1324 AlignFrame.this.setTitle(file);
1325 statusBar.setText(MessageManager.formatMessage(
1326 "label.successfully_saved_to_file_in_format", new Object[]
1327 { fileName, format.getName() }));
1328 lastSaveSuccessful = true;
1329 } catch (IOException e)
1331 lastSaveSuccessful = false;
1333 "ALIGNFRAME Something happened writing the temp file");
1334 Console.error(e.getMessage());
1335 Console.debug(Cache.getStackTraceString(e));
1336 } catch (Exception ex)
1338 lastSaveSuccessful = false;
1340 "ALIGNFRAME Something unexpected happened writing the temp file");
1341 Console.error(ex.getMessage());
1342 Console.debug(Cache.getStackTraceString(ex));
1347 backupfiles.setWriteSuccess(lastSaveSuccessful);
1348 Console.debug("ALIGNFRAME writing temp file was "
1349 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1350 // do the backup file roll and rename the temp file to actual file
1351 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1352 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1353 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1354 + (lastSaveSuccessful ? "" : "un") + "successfully");
1357 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1358 if (lastSaveSuccessful)
1360 AlignFrame.this.getViewport().setSavedUpToDate(true);
1366 * show dialog with export options if applicable; else just do it
1368 if (AlignExportOptions.isNeeded(viewport, format))
1370 AlignExportOptions choices = new AlignExportOptions(
1371 alignPanel.getAlignViewport(), format, options);
1372 choices.setResponseAction(0, outputAction);
1373 choices.setResponseAction(1, cancelAction);
1374 choices.showDialog();
1381 } catch (Exception e)
1383 // TODO Auto-generated catch block
1384 e.printStackTrace();
1390 * Outputs the alignment to textbox in the requested format, if necessary
1391 * first prompting the user for whether to include hidden regions or
1394 * @param fileFormatName
1397 protected void outputText_actionPerformed(String fileFormatName)
1399 FileFormatI fileFormat = FileFormats.getInstance()
1400 .forName(fileFormatName);
1401 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1402 Runnable outputAction = () -> {
1403 // todo defer this to inside formatSequences (or later)
1404 AlignmentExportData exportData = viewport.getAlignExportData(options);
1405 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1406 cap.setForInput(null);
1409 FileFormatI format = fileFormat;
1410 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1411 format, exportData.getAlignment(),
1412 exportData.getOmitHidden(),
1413 exportData.getStartEndPostions(),
1414 viewport.getAlignment().getHiddenColumns()));
1415 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1416 "label.alignment_output_command", new Object[]
1417 { fileFormat.getName() }), 600, 500);
1418 } catch (OutOfMemoryError oom)
1420 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1427 * show dialog with export options if applicable; else just do it
1429 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1431 AlignExportOptions choices = new AlignExportOptions(
1432 alignPanel.getAlignViewport(), fileFormat, options);
1433 choices.setResponseAction(0, outputAction);
1434 choices.showDialog();
1441 } catch (Exception e)
1443 e.printStackTrace();
1455 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1457 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1460 htmlSVG.exportHTML(null);
1461 } catch (ImageOutputException x)
1463 // report problem to console and raise dialog
1468 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1470 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1473 bjs.exportHTML(null);
1474 } catch (ImageOutputException x)
1476 // report problem to console and raise dialog
1480 public void createImageMap(File file, String image)
1484 alignPanel.makePNGImageMap(file, image);
1485 } catch (ImageOutputException x)
1487 // report problem to console and raise dialog
1492 public void createPNG_actionPerformed(ActionEvent e)
1497 } catch (ImageOutputException ioex)
1499 // raise dialog, and report via console
1504 public void createEPS_actionPerformed(ActionEvent e)
1509 } catch (ImageOutputException ioex)
1511 // raise dialog, and report via console
1517 public void createSVG_actionPerformed(ActionEvent e)
1522 } catch (ImageOutputException ioex)
1524 // raise dialog, and report via console
1530 * Creates a PNG image of the alignment and writes it to the given file. If
1531 * the file is null, the user is prompted to choose a file.
1535 public void createPNG(File f) throws ImageOutputException
1537 createPNG(f, null, BitmapImageSizing.nullBitmapImageSizing());
1540 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1541 throws ImageOutputException
1543 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1547 * Creates an EPS image of the alignment and writes it to the given file. If
1548 * the file is null, the user is prompted to choose a file.
1552 public void createEPS(File f) throws ImageOutputException
1557 public void createEPS(File f, String renderer) throws ImageOutputException
1559 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1563 * Creates an SVG image of the alignment and writes it to the given file. If
1564 * the file is null, the user is prompted to choose a file.
1568 public void createSVG(File f) throws ImageOutputException
1573 public void createSVG(File f, String renderer) throws ImageOutputException
1575 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1579 public void pageSetup_actionPerformed(ActionEvent e)
1581 PrinterJob printJob = PrinterJob.getPrinterJob();
1582 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1592 public void printMenuItem_actionPerformed(ActionEvent e)
1594 // Putting in a thread avoids Swing painting problems
1595 PrintThread thread = new PrintThread(alignPanel);
1600 public void exportFeatures_actionPerformed(ActionEvent e)
1602 new AnnotationExporter(alignPanel).exportFeatures();
1606 public void exportAnnotations_actionPerformed(ActionEvent e)
1608 new AnnotationExporter(alignPanel).exportAnnotations();
1612 public void associatedData_actionPerformed(ActionEvent e)
1614 final JalviewFileChooser chooser = new JalviewFileChooser(
1615 Cache.getProperty("LAST_DIRECTORY"));
1616 chooser.setFileView(new JalviewFileView());
1617 String tooltip = MessageManager
1618 .getString("label.load_jalview_annotations");
1619 chooser.setDialogTitle(tooltip);
1620 chooser.setToolTipText(tooltip);
1621 chooser.setResponseHandler(0, () -> {
1622 String choice = chooser.getSelectedFile().getPath();
1623 Cache.setProperty("LAST_DIRECTORY", choice);
1624 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1627 chooser.showOpenDialog(this);
1631 * Close the current view or all views in the alignment frame. If the frame
1632 * only contains one view then the alignment will be removed from memory.
1634 * @param closeAllTabs
1637 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1639 if (alignPanels != null && alignPanels.size() < 2)
1641 closeAllTabs = true;
1646 if (alignPanels != null)
1650 if (this.isClosed())
1652 // really close all the windows - otherwise wait till
1653 // setClosed(true) is called
1654 for (int i = 0; i < alignPanels.size(); i++)
1656 AlignmentPanel ap = alignPanels.get(i);
1663 closeView(alignPanel);
1668 if (featureSettings != null && featureSettings.isOpen())
1670 featureSettings.close();
1671 featureSettings = null;
1674 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1675 * be called recursively, with the frame now in 'closed' state
1677 this.setClosed(true);
1679 } catch (Exception ex)
1681 ex.printStackTrace();
1686 * Close the specified panel and close up tabs appropriately.
1688 * @param panelToClose
1690 public void closeView(AlignmentPanel panelToClose)
1692 int index = tabbedPane.getSelectedIndex();
1693 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1694 alignPanels.remove(panelToClose);
1695 panelToClose.closePanel();
1696 panelToClose = null;
1698 tabbedPane.removeTabAt(closedindex);
1699 tabbedPane.validate();
1701 if (index > closedindex || index == tabbedPane.getTabCount())
1703 // modify currently selected tab index if necessary.
1707 this.tabSelectionChanged(index);
1713 void updateEditMenuBar()
1716 if (viewport.getHistoryList().size() > 0)
1718 undoMenuItem.setEnabled(true);
1719 CommandI command = viewport.getHistoryList().peek();
1720 undoMenuItem.setText(MessageManager
1721 .formatMessage("label.undo_command", new Object[]
1722 { command.getDescription() }));
1726 undoMenuItem.setEnabled(false);
1727 undoMenuItem.setText(MessageManager.getString("action.undo"));
1730 if (viewport.getRedoList().size() > 0)
1732 redoMenuItem.setEnabled(true);
1734 CommandI command = viewport.getRedoList().peek();
1735 redoMenuItem.setText(MessageManager
1736 .formatMessage("label.redo_command", new Object[]
1737 { command.getDescription() }));
1741 redoMenuItem.setEnabled(false);
1742 redoMenuItem.setText(MessageManager.getString("action.redo"));
1747 public void addHistoryItem(CommandI command)
1749 if (command.getSize() > 0)
1751 viewport.addToHistoryList(command);
1752 viewport.clearRedoList();
1753 updateEditMenuBar();
1754 viewport.updateHiddenColumns();
1755 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1756 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1757 // viewport.getColumnSelection()
1758 // .getHiddenColumns().size() > 0);
1764 * @return alignment objects for all views
1766 AlignmentI[] getViewAlignments()
1768 if (alignPanels != null)
1770 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1772 for (AlignmentPanel ap : alignPanels)
1774 als[i++] = ap.av.getAlignment();
1778 if (viewport != null)
1780 return new AlignmentI[] { viewport.getAlignment() };
1792 protected void undoMenuItem_actionPerformed(ActionEvent e)
1794 if (viewport.getHistoryList().isEmpty())
1798 CommandI command = viewport.getHistoryList().pop();
1799 viewport.addToRedoList(command);
1800 command.undoCommand(getViewAlignments());
1802 AlignmentViewport originalSource = getOriginatingSource(command);
1803 updateEditMenuBar();
1805 if (originalSource != null)
1807 if (originalSource != viewport)
1810 "Implementation worry: mismatch of viewport origin for undo");
1812 originalSource.updateHiddenColumns();
1813 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1815 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1816 // viewport.getColumnSelection()
1817 // .getHiddenColumns().size() > 0);
1818 originalSource.firePropertyChange("alignment", null,
1819 originalSource.getAlignment().getSequences());
1830 protected void redoMenuItem_actionPerformed(ActionEvent e)
1832 if (viewport.getRedoList().size() < 1)
1837 CommandI command = viewport.getRedoList().pop();
1838 viewport.addToHistoryList(command);
1839 command.doCommand(getViewAlignments());
1841 AlignmentViewport originalSource = getOriginatingSource(command);
1842 updateEditMenuBar();
1844 if (originalSource != null)
1847 if (originalSource != viewport)
1850 "Implementation worry: mismatch of viewport origin for redo");
1852 originalSource.updateHiddenColumns();
1853 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1855 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1856 // viewport.getColumnSelection()
1857 // .getHiddenColumns().size() > 0);
1858 originalSource.firePropertyChange("alignment", null,
1859 originalSource.getAlignment().getSequences());
1863 AlignmentViewport getOriginatingSource(CommandI command)
1865 AlignmentViewport originalSource = null;
1866 // For sequence removal and addition, we need to fire
1867 // the property change event FROM the viewport where the
1868 // original alignment was altered
1869 AlignmentI al = null;
1870 if (command instanceof EditCommand)
1872 EditCommand editCommand = (EditCommand) command;
1873 al = editCommand.getAlignment();
1874 List<Component> comps = PaintRefresher.components
1875 .get(viewport.getSequenceSetId());
1877 for (Component comp : comps)
1879 if (comp instanceof AlignmentPanel)
1881 if (al == ((AlignmentPanel) comp).av.getAlignment())
1883 originalSource = ((AlignmentPanel) comp).av;
1890 if (originalSource == null)
1892 // The original view is closed, we must validate
1893 // the current view against the closed view first
1896 PaintRefresher.validateSequences(al, viewport.getAlignment());
1899 originalSource = viewport;
1902 return originalSource;
1906 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1907 * or the sequence under cursor in keyboard mode
1912 public void moveSelectedSequences(boolean up)
1914 SequenceGroup sg = viewport.getSelectionGroup();
1918 if (viewport.cursorMode)
1920 sg = new SequenceGroup();
1921 sg.addSequence(viewport.getAlignment().getSequenceAt(
1922 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1930 if (sg.getSize() < 1)
1935 // TODO: JAL-3733 - add an event to the undo buffer for this !
1937 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1938 viewport.getHiddenRepSequences(), up);
1939 alignPanel.paintAlignment(true, false);
1942 synchronized void slideSequences(boolean right, int size)
1944 List<SequenceI> sg = new ArrayList<>();
1945 if (viewport.cursorMode)
1947 sg.add(viewport.getAlignment()
1948 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1950 else if (viewport.getSelectionGroup() != null
1951 && viewport.getSelectionGroup().getSize() != viewport
1952 .getAlignment().getHeight())
1954 sg = viewport.getSelectionGroup()
1955 .getSequences(viewport.getHiddenRepSequences());
1963 List<SequenceI> invertGroup = new ArrayList<>();
1965 for (SequenceI seq : viewport.getAlignment().getSequences())
1967 if (!sg.contains(seq))
1969 invertGroup.add(seq);
1973 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
1975 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
1976 for (int i = 0; i < invertGroup.size(); i++)
1978 seqs2[i] = invertGroup.get(i);
1981 SlideSequencesCommand ssc;
1984 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
1985 viewport.getGapCharacter());
1989 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
1990 viewport.getGapCharacter());
1993 int groupAdjustment = 0;
1994 if (ssc.getGapsInsertedBegin() && right)
1996 if (viewport.cursorMode)
1998 alignPanel.getSeqPanel().moveCursor(size, 0);
2002 groupAdjustment = size;
2005 else if (!ssc.getGapsInsertedBegin() && !right)
2007 if (viewport.cursorMode)
2009 alignPanel.getSeqPanel().moveCursor(-size, 0);
2013 groupAdjustment = -size;
2017 if (groupAdjustment != 0)
2019 viewport.getSelectionGroup().setStartRes(
2020 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2021 viewport.getSelectionGroup().setEndRes(
2022 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2026 * just extend the last slide command if compatible; but not if in
2027 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2029 boolean appendHistoryItem = false;
2030 Deque<CommandI> historyList = viewport.getHistoryList();
2031 boolean inSplitFrame = getSplitViewContainer() != null;
2032 if (!inSplitFrame && historyList != null && historyList.size() > 0
2033 && historyList.peek() instanceof SlideSequencesCommand)
2035 appendHistoryItem = ssc.appendSlideCommand(
2036 (SlideSequencesCommand) historyList.peek());
2039 if (!appendHistoryItem)
2041 addHistoryItem(ssc);
2054 protected void copy_actionPerformed()
2056 if (viewport.getSelectionGroup() == null)
2060 // TODO: preserve the ordering of displayed alignment annotation in any
2061 // internal paste (particularly sequence associated annotation)
2062 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2063 String[] omitHidden = null;
2065 if (viewport.hasHiddenColumns())
2067 omitHidden = viewport.getViewAsString(true);
2070 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2071 seqs, omitHidden, null);
2073 StringSelection ss = new StringSelection(output);
2077 jalview.gui.Desktop.internalCopy = true;
2078 // Its really worth setting the clipboard contents
2079 // to empty before setting the large StringSelection!!
2080 Toolkit.getDefaultToolkit().getSystemClipboard()
2081 .setContents(new StringSelection(""), null);
2083 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2085 } catch (OutOfMemoryError er)
2087 new OOMWarning("copying region", er);
2091 HiddenColumns hiddenColumns = null;
2092 if (viewport.hasHiddenColumns())
2094 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2095 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2097 // create new HiddenColumns object with copy of hidden regions
2098 // between startRes and endRes, offset by startRes
2099 hiddenColumns = new HiddenColumns(
2100 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2101 hiddenCutoff, hiddenOffset);
2104 Desktop.jalviewClipboard = new Object[] { seqs,
2105 viewport.getAlignment().getDataset(), hiddenColumns };
2106 setStatus(MessageManager.formatMessage(
2107 "label.copied_sequences_to_clipboard", new Object[]
2108 { Integer.valueOf(seqs.length).toString() }));
2118 protected void pasteNew_actionPerformed(ActionEvent e)
2130 protected void pasteThis_actionPerformed(ActionEvent e)
2136 * Paste contents of Jalview clipboard
2138 * @param newAlignment
2139 * true to paste to a new alignment, otherwise add to this.
2141 void paste(boolean newAlignment)
2143 boolean externalPaste = true;
2146 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2147 Transferable contents = c.getContents(this);
2149 if (contents == null)
2158 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2159 if (str.length() < 1)
2164 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2166 } catch (OutOfMemoryError er)
2168 new OOMWarning("Out of memory pasting sequences!!", er);
2172 SequenceI[] sequences;
2173 boolean annotationAdded = false;
2174 AlignmentI alignment = null;
2176 if (Desktop.jalviewClipboard != null)
2178 // The clipboard was filled from within Jalview, we must use the
2180 // And dataset from the copied alignment
2181 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2182 // be doubly sure that we create *new* sequence objects.
2183 sequences = new SequenceI[newseq.length];
2184 for (int i = 0; i < newseq.length; i++)
2186 sequences[i] = new Sequence(newseq[i]);
2188 alignment = new Alignment(sequences);
2189 externalPaste = false;
2193 // parse the clipboard as an alignment.
2194 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2196 sequences = alignment.getSequencesArray();
2200 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2206 if (Desktop.jalviewClipboard != null)
2208 // dataset is inherited
2209 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2213 // new dataset is constructed
2214 alignment.setDataset(null);
2216 alwidth = alignment.getWidth() + 1;
2220 AlignmentI pastedal = alignment; // preserve pasted alignment object
2221 // Add pasted sequences and dataset into existing alignment.
2222 alignment = viewport.getAlignment();
2223 alwidth = alignment.getWidth() + 1;
2224 // decide if we need to import sequences from an existing dataset
2225 boolean importDs = Desktop.jalviewClipboard != null
2226 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2227 // importDs==true instructs us to copy over new dataset sequences from
2228 // an existing alignment
2229 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2231 // minimum dataset set
2233 for (int i = 0; i < sequences.length; i++)
2237 newDs.addElement(null);
2239 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2241 if (importDs && ds != null)
2243 if (!newDs.contains(ds))
2245 newDs.setElementAt(ds, i);
2246 ds = new Sequence(ds);
2247 // update with new dataset sequence
2248 sequences[i].setDatasetSequence(ds);
2252 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2257 // copy and derive new dataset sequence
2258 sequences[i] = sequences[i].deriveSequence();
2259 alignment.getDataset()
2260 .addSequence(sequences[i].getDatasetSequence());
2261 // TODO: avoid creation of duplicate dataset sequences with a
2262 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2264 alignment.addSequence(sequences[i]); // merges dataset
2268 newDs.clear(); // tidy up
2270 if (alignment.getAlignmentAnnotation() != null)
2272 for (AlignmentAnnotation alan : alignment
2273 .getAlignmentAnnotation())
2275 if (alan.graphGroup > fgroup)
2277 fgroup = alan.graphGroup;
2281 if (pastedal.getAlignmentAnnotation() != null)
2283 // Add any annotation attached to alignment.
2284 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2285 for (int i = 0; i < alann.length; i++)
2287 annotationAdded = true;
2288 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2290 AlignmentAnnotation newann = new AlignmentAnnotation(
2292 if (newann.graphGroup > -1)
2294 if (newGraphGroups.size() <= newann.graphGroup
2295 || newGraphGroups.get(newann.graphGroup) == null)
2297 for (int q = newGraphGroups
2298 .size(); q <= newann.graphGroup; q++)
2300 newGraphGroups.add(q, null);
2302 newGraphGroups.set(newann.graphGroup,
2303 Integer.valueOf(++fgroup));
2305 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2309 newann.padAnnotation(alwidth);
2310 alignment.addAnnotation(newann);
2320 addHistoryItem(new EditCommand(
2321 MessageManager.getString("label.add_sequences"),
2322 Action.PASTE, sequences, 0, alignment.getWidth(),
2325 // Add any annotations attached to sequences
2326 for (int i = 0; i < sequences.length; i++)
2328 if (sequences[i].getAnnotation() != null)
2330 AlignmentAnnotation newann;
2331 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2333 annotationAdded = true;
2334 newann = sequences[i].getAnnotation()[a];
2335 newann.adjustForAlignment();
2336 newann.padAnnotation(alwidth);
2337 if (newann.graphGroup > -1)
2339 if (newann.graphGroup > -1)
2341 if (newGraphGroups.size() <= newann.graphGroup
2342 || newGraphGroups.get(newann.graphGroup) == null)
2344 for (int q = newGraphGroups
2345 .size(); q <= newann.graphGroup; q++)
2347 newGraphGroups.add(q, null);
2349 newGraphGroups.set(newann.graphGroup,
2350 Integer.valueOf(++fgroup));
2352 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2356 // annotation was duplicated earlier
2357 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2358 // take care of contact matrix too
2359 ContactMatrixI cm = sequences[i]
2360 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2363 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2367 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2375 // propagate alignment changed.
2376 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2377 if (annotationAdded)
2379 // Duplicate sequence annotation in all views.
2380 AlignmentI[] alview = this.getViewAlignments();
2381 for (int i = 0; i < sequences.length; i++)
2383 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2388 for (int avnum = 0; avnum < alview.length; avnum++)
2390 if (alview[avnum] != alignment)
2392 // duplicate in a view other than the one with input focus
2393 int avwidth = alview[avnum].getWidth() + 1;
2394 // this relies on sann being preserved after we
2395 // modify the sequence's annotation array for each duplication
2396 for (int a = 0; a < sann.length; a++)
2398 AlignmentAnnotation newann = new AlignmentAnnotation(
2400 sequences[i].addAlignmentAnnotation(newann);
2401 newann.padAnnotation(avwidth);
2402 alview[avnum].addAnnotation(newann); // annotation was
2403 // duplicated earlier
2404 // TODO JAL-1145 graphGroups are not updated for sequence
2405 // annotation added to several views. This may cause
2407 alview[avnum].setAnnotationIndex(newann, a);
2412 buildSortByAnnotationScoresMenu();
2414 viewport.firePropertyChange("alignment", null,
2415 alignment.getSequences());
2416 if (alignPanels != null)
2418 for (AlignmentPanel ap : alignPanels)
2420 ap.validateAnnotationDimensions(false);
2425 alignPanel.validateAnnotationDimensions(false);
2431 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2433 String newtitle = new String("Copied sequences");
2435 if (Desktop.jalviewClipboard != null
2436 && Desktop.jalviewClipboard[2] != null)
2438 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2439 af.viewport.setHiddenColumns(hc);
2442 // >>>This is a fix for the moment, until a better solution is
2444 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2445 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2446 .getFeatureRenderer());
2448 // TODO: maintain provenance of an alignment, rather than just make the
2449 // title a concatenation of operations.
2452 if (title.startsWith("Copied sequences"))
2458 newtitle = newtitle.concat("- from " + title);
2463 newtitle = new String("Pasted sequences");
2466 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2471 } catch (Exception ex)
2473 ex.printStackTrace();
2474 System.out.println("Exception whilst pasting: " + ex);
2475 // could be anything being pasted in here
2481 protected void expand_newalign(ActionEvent e)
2485 AlignmentI alignment = AlignmentUtils
2486 .expandContext(getViewport().getAlignment(), -1);
2487 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2489 String newtitle = new String("Flanking alignment");
2491 if (Desktop.jalviewClipboard != null
2492 && Desktop.jalviewClipboard[2] != null)
2494 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2495 af.viewport.setHiddenColumns(hc);
2498 // >>>This is a fix for the moment, until a better solution is
2500 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2501 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2502 .getFeatureRenderer());
2504 // TODO: maintain provenance of an alignment, rather than just make the
2505 // title a concatenation of operations.
2507 if (title.startsWith("Copied sequences"))
2513 newtitle = newtitle.concat("- from " + title);
2517 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2519 } catch (Exception ex)
2521 ex.printStackTrace();
2522 System.out.println("Exception whilst pasting: " + ex);
2523 // could be anything being pasted in here
2524 } catch (OutOfMemoryError oom)
2526 new OOMWarning("Viewing flanking region of alignment", oom);
2531 * Action Cut (delete and copy) the selected region
2534 protected void cut_actionPerformed()
2536 copy_actionPerformed();
2537 delete_actionPerformed();
2541 * Performs menu option to Delete the currently selected region
2544 protected void delete_actionPerformed()
2547 SequenceGroup sg = viewport.getSelectionGroup();
2553 Runnable okAction = () -> {
2554 SequenceI[] cut = sg.getSequences()
2555 .toArray(new SequenceI[sg.getSize()]);
2557 addHistoryItem(new EditCommand(
2558 MessageManager.getString("label.cut_sequences"), Action.CUT,
2559 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2560 viewport.getAlignment()));
2562 viewport.setSelectionGroup(null);
2563 viewport.sendSelection();
2564 viewport.getAlignment().deleteGroup(sg);
2566 viewport.firePropertyChange("alignment", null,
2567 viewport.getAlignment().getSequences());
2568 if (viewport.getAlignment().getHeight() < 1)
2572 AlignFrame.this.setClosed(true);
2573 } catch (Exception ex)
2580 * If the cut affects all sequences, prompt for confirmation
2582 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2584 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2585 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2586 if (wholeHeight && wholeWidth)
2588 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2589 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2590 Object[] options = new Object[] {
2591 MessageManager.getString("action.ok"),
2592 MessageManager.getString("action.cancel") };
2593 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2594 MessageManager.getString("label.delete_all"),
2595 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2596 options, options[0]);
2603 } catch (Exception e)
2605 e.printStackTrace();
2617 protected void deleteGroups_actionPerformed(ActionEvent e)
2619 if (avc.deleteGroups())
2621 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2622 alignPanel.updateAnnotation();
2623 alignPanel.paintAlignment(true, true);
2634 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2636 SequenceGroup sg = new SequenceGroup(
2637 viewport.getAlignment().getSequences());
2639 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2640 viewport.setSelectionGroup(sg);
2641 viewport.isSelectionGroupChanged(true);
2642 viewport.sendSelection();
2643 // JAL-2034 - should delegate to
2644 // alignPanel to decide if overview needs
2646 alignPanel.paintAlignment(false, false);
2647 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2657 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2659 if (viewport.cursorMode)
2661 alignPanel.getSeqPanel().keyboardNo1 = null;
2662 alignPanel.getSeqPanel().keyboardNo2 = null;
2664 viewport.setSelectionGroup(null);
2665 viewport.getColumnSelection().clear();
2666 viewport.setSearchResults(null);
2667 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2668 // JAL-2034 - should delegate to
2669 // alignPanel to decide if overview needs
2671 alignPanel.paintAlignment(false, false);
2672 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2673 viewport.sendSelection();
2683 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2685 SequenceGroup sg = viewport.getSelectionGroup();
2689 selectAllSequenceMenuItem_actionPerformed(null);
2694 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2696 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2698 // JAL-2034 - should delegate to
2699 // alignPanel to decide if overview needs
2702 alignPanel.paintAlignment(true, false);
2703 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2704 viewport.sendSelection();
2708 public void invertColSel_actionPerformed(ActionEvent e)
2710 viewport.invertColumnSelection();
2711 alignPanel.paintAlignment(true, false);
2712 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2713 viewport.sendSelection();
2723 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2725 trimAlignment(true);
2735 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2737 trimAlignment(false);
2740 void trimAlignment(boolean trimLeft)
2742 ColumnSelection colSel = viewport.getColumnSelection();
2745 if (!colSel.isEmpty())
2749 column = colSel.getMin();
2753 column = colSel.getMax();
2757 if (viewport.getSelectionGroup() != null)
2759 seqs = viewport.getSelectionGroup()
2760 .getSequencesAsArray(viewport.getHiddenRepSequences());
2764 seqs = viewport.getAlignment().getSequencesArray();
2767 TrimRegionCommand trimRegion;
2770 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2771 column, viewport.getAlignment());
2772 viewport.getRanges().setStartRes(0);
2776 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2777 column, viewport.getAlignment());
2780 setStatus(MessageManager.formatMessage("label.removed_columns",
2782 { Integer.valueOf(trimRegion.getSize()).toString() }));
2784 addHistoryItem(trimRegion);
2786 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2788 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2789 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2791 viewport.getAlignment().deleteGroup(sg);
2795 viewport.firePropertyChange("alignment", null,
2796 viewport.getAlignment().getSequences());
2807 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2809 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2812 if (viewport.getSelectionGroup() != null)
2814 seqs = viewport.getSelectionGroup()
2815 .getSequencesAsArray(viewport.getHiddenRepSequences());
2816 start = viewport.getSelectionGroup().getStartRes();
2817 end = viewport.getSelectionGroup().getEndRes();
2821 seqs = viewport.getAlignment().getSequencesArray();
2824 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2825 "Remove Gapped Columns", seqs, start, end,
2826 viewport.getAlignment());
2828 addHistoryItem(removeGapCols);
2830 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2832 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2834 // This is to maintain viewport position on first residue
2835 // of first sequence
2836 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2837 ViewportRanges ranges = viewport.getRanges();
2838 int startRes = seq.findPosition(ranges.getStartRes());
2839 // ShiftList shifts;
2840 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2841 // edit.alColumnChanges=shifts.getInverse();
2842 // if (viewport.hasHiddenColumns)
2843 // viewport.getColumnSelection().compensateForEdits(shifts);
2844 ranges.setStartRes(seq.findIndex(startRes) - 1);
2845 viewport.firePropertyChange("alignment", null,
2846 viewport.getAlignment().getSequences());
2857 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2859 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2862 if (viewport.getSelectionGroup() != null)
2864 seqs = viewport.getSelectionGroup()
2865 .getSequencesAsArray(viewport.getHiddenRepSequences());
2866 start = viewport.getSelectionGroup().getStartRes();
2867 end = viewport.getSelectionGroup().getEndRes();
2871 seqs = viewport.getAlignment().getSequencesArray();
2874 // This is to maintain viewport position on first residue
2875 // of first sequence
2876 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2877 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2879 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2880 viewport.getAlignment()));
2882 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2884 viewport.firePropertyChange("alignment", null,
2885 viewport.getAlignment().getSequences());
2896 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2898 viewport.setPadGaps(padGapsMenuitem.isSelected());
2899 viewport.firePropertyChange("alignment", null,
2900 viewport.getAlignment().getSequences());
2904 * Opens a Finder dialog
2909 public void findMenuItem_actionPerformed(ActionEvent e)
2911 new Finder(alignPanel, false, null);
2915 * Create a new view of the current alignment.
2918 public void newView_actionPerformed(ActionEvent e)
2920 newView(null, true);
2924 * Creates and shows a new view of the current alignment.
2927 * title of newly created view; if null, one will be generated
2928 * @param copyAnnotation
2929 * if true then duplicate all annnotation, groups and settings
2930 * @return new alignment panel, already displayed.
2932 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2935 * Create a new AlignmentPanel (with its own, new Viewport)
2937 AlignmentPanel newap = new jalview.project.Jalview2XML()
2938 .copyAlignPanel(alignPanel);
2939 if (!copyAnnotation)
2942 * remove all groups and annotation except for the automatic stuff
2944 newap.av.getAlignment().deleteAllGroups();
2945 newap.av.getAlignment().deleteAllAnnotations(false);
2948 newap.av.setGatherViewsHere(false);
2950 if (viewport.getViewName() == null)
2952 viewport.setViewName(
2953 MessageManager.getString("label.view_name_original"));
2957 * Views share the same edits undo and redo stacks
2959 newap.av.setHistoryList(viewport.getHistoryList());
2960 newap.av.setRedoList(viewport.getRedoList());
2963 * copy any visualisation settings that are not saved in the project
2965 newap.av.setColourAppliesToAllGroups(
2966 viewport.getColourAppliesToAllGroups());
2969 * Views share the same mappings; need to deregister any new mappings
2970 * created by copyAlignPanel, and register the new reference to the shared
2973 newap.av.replaceMappings(viewport.getAlignment());
2976 * start up cDNA consensus (if applicable) now mappings are in place
2978 if (newap.av.initComplementConsensus())
2980 newap.refresh(true); // adjust layout of annotations
2983 newap.av.setViewName(getNewViewName(viewTitle));
2985 addAlignmentPanel(newap, true);
2986 newap.alignmentChanged();
2988 if (alignPanels.size() == 2)
2990 viewport.setGatherViewsHere(true);
2992 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
2998 * Make a new name for the view, ensuring it is unique within the current
2999 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3000 * these now use viewId. Unique view names are still desirable for usability.)
3005 protected String getNewViewName(String viewTitle)
3007 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3008 boolean addFirstIndex = false;
3009 if (viewTitle == null || viewTitle.trim().length() == 0)
3011 viewTitle = MessageManager.getString("action.view");
3012 addFirstIndex = true;
3016 index = 1;// we count from 1 if given a specific name
3018 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3020 List<Component> comps = PaintRefresher.components
3021 .get(viewport.getSequenceSetId());
3023 List<String> existingNames = getExistingViewNames(comps);
3025 while (existingNames.contains(newViewName))
3027 newViewName = viewTitle + " " + (++index);
3033 * Returns a list of distinct view names found in the given list of
3034 * components. View names are held on the viewport of an AlignmentPanel.
3039 protected List<String> getExistingViewNames(List<Component> comps)
3041 List<String> existingNames = new ArrayList<>();
3042 for (Component comp : comps)
3044 if (comp instanceof AlignmentPanel)
3046 AlignmentPanel ap = (AlignmentPanel) comp;
3047 if (!existingNames.contains(ap.av.getViewName()))
3049 existingNames.add(ap.av.getViewName());
3053 return existingNames;
3057 * Explode tabbed views into separate windows.
3060 public void expandViews_actionPerformed(ActionEvent e)
3062 Desktop.explodeViews(this);
3066 * Gather views in separate windows back into a tabbed presentation.
3069 public void gatherViews_actionPerformed(ActionEvent e)
3071 Desktop.instance.gatherViews(this);
3081 public void font_actionPerformed(ActionEvent e)
3083 new FontChooser(alignPanel);
3093 protected void seqLimit_actionPerformed(ActionEvent e)
3095 viewport.setShowJVSuffix(seqLimits.isSelected());
3097 alignPanel.getIdPanel().getIdCanvas()
3098 .setPreferredSize(alignPanel.calculateIdWidth());
3099 alignPanel.paintAlignment(true, false);
3103 public void idRightAlign_actionPerformed(ActionEvent e)
3105 viewport.setRightAlignIds(idRightAlign.isSelected());
3106 alignPanel.paintAlignment(false, false);
3110 public void centreColumnLabels_actionPerformed(ActionEvent e)
3112 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3113 alignPanel.paintAlignment(false, false);
3119 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3122 protected void followHighlight_actionPerformed()
3125 * Set the 'follow' flag on the Viewport (and scroll to position if now
3128 final boolean state = this.followHighlightMenuItem.getState();
3129 viewport.setFollowHighlight(state);
3132 alignPanel.scrollToPosition(viewport.getSearchResults());
3143 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3145 viewport.setColourText(colourTextMenuItem.isSelected());
3146 alignPanel.paintAlignment(false, false);
3156 public void wrapMenuItem_actionPerformed(ActionEvent e)
3158 setWrapFormat(wrapMenuItem.isSelected());
3161 public void setWrapFormat(boolean b)
3163 scaleAbove.setVisible(b);
3164 scaleLeft.setVisible(b);
3165 scaleRight.setVisible(b);
3166 viewport.setWrapAlignment(b);
3167 alignPanel.updateLayout();
3171 public void showAllSeqs_actionPerformed(ActionEvent e)
3173 viewport.showAllHiddenSeqs();
3177 public void showAllColumns_actionPerformed(ActionEvent e)
3179 viewport.showAllHiddenColumns();
3180 alignPanel.paintAlignment(true, true);
3181 viewport.sendSelection();
3185 public void hideSelSequences_actionPerformed(ActionEvent e)
3187 viewport.hideAllSelectedSeqs();
3191 * called by key handler and the hide all/show all menu items
3196 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3199 boolean hide = false;
3200 SequenceGroup sg = viewport.getSelectionGroup();
3201 if (!toggleSeqs && !toggleCols)
3203 // Hide everything by the current selection - this is a hack - we do the
3204 // invert and then hide
3205 // first check that there will be visible columns after the invert.
3206 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3207 && sg.getStartRes() <= sg.getEndRes()))
3209 // now invert the sequence set, if required - empty selection implies
3210 // that no hiding is required.
3213 invertSequenceMenuItem_actionPerformed(null);
3214 sg = viewport.getSelectionGroup();
3218 viewport.expandColSelection(sg, true);
3219 // finally invert the column selection and get the new sequence
3221 invertColSel_actionPerformed(null);
3228 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3230 hideSelSequences_actionPerformed(null);
3233 else if (!(toggleCols && viewport.hasSelectedColumns()))
3235 showAllSeqs_actionPerformed(null);
3241 if (viewport.hasSelectedColumns())
3243 hideSelColumns_actionPerformed(null);
3246 viewport.setSelectionGroup(sg);
3251 showAllColumns_actionPerformed(null);
3260 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3261 * event.ActionEvent)
3264 public void hideAllButSelection_actionPerformed(ActionEvent e)
3266 toggleHiddenRegions(false, false);
3267 viewport.sendSelection();
3274 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3278 public void hideAllSelection_actionPerformed(ActionEvent e)
3280 SequenceGroup sg = viewport.getSelectionGroup();
3281 viewport.expandColSelection(sg, false);
3282 viewport.hideAllSelectedSeqs();
3283 viewport.hideSelectedColumns();
3284 alignPanel.updateLayout();
3285 alignPanel.paintAlignment(true, true);
3286 viewport.sendSelection();
3293 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3297 public void showAllhidden_actionPerformed(ActionEvent e)
3299 viewport.showAllHiddenColumns();
3300 viewport.showAllHiddenSeqs();
3301 alignPanel.paintAlignment(true, true);
3302 viewport.sendSelection();
3306 public void hideSelColumns_actionPerformed(ActionEvent e)
3308 viewport.hideSelectedColumns();
3309 alignPanel.updateLayout();
3310 alignPanel.paintAlignment(true, true);
3311 viewport.sendSelection();
3315 public void hiddenMarkers_actionPerformed(ActionEvent e)
3317 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3328 protected void scaleAbove_actionPerformed(ActionEvent e)
3330 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3331 alignPanel.updateLayout();
3332 alignPanel.paintAlignment(true, false);
3342 protected void scaleLeft_actionPerformed(ActionEvent e)
3344 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3345 alignPanel.updateLayout();
3346 alignPanel.paintAlignment(true, false);
3356 protected void scaleRight_actionPerformed(ActionEvent e)
3358 viewport.setScaleRightWrapped(scaleRight.isSelected());
3359 alignPanel.updateLayout();
3360 alignPanel.paintAlignment(true, false);
3370 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3372 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3373 alignPanel.paintAlignment(false, false);
3383 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3385 viewport.setShowText(viewTextMenuItem.isSelected());
3386 alignPanel.paintAlignment(false, false);
3396 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3398 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3399 alignPanel.paintAlignment(false, false);
3402 public FeatureSettings featureSettings;
3405 public FeatureSettingsControllerI getFeatureSettingsUI()
3407 return featureSettings;
3411 public void featureSettings_actionPerformed(ActionEvent e)
3413 showFeatureSettingsUI();
3417 public FeatureSettingsControllerI showFeatureSettingsUI()
3419 if (featureSettings != null)
3421 featureSettings.closeOldSettings();
3422 featureSettings = null;
3424 if (!showSeqFeatures.isSelected())
3426 // make sure features are actually displayed
3427 showSeqFeatures.setSelected(true);
3428 showSeqFeatures_actionPerformed(null);
3430 featureSettings = new FeatureSettings(this);
3431 return featureSettings;
3435 * Set or clear 'Show Sequence Features'
3441 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3443 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3444 alignPanel.paintAlignment(true, true);
3448 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3449 * the annotations panel as a whole.
3451 * The options to show/hide all annotations should be enabled when the panel
3452 * is shown, and disabled when the panel is hidden.
3457 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3459 final boolean setVisible = annotationPanelMenuItem.isSelected();
3460 viewport.setShowAnnotation(setVisible);
3461 this.showAllSeqAnnotations.setEnabled(setVisible);
3462 this.hideAllSeqAnnotations.setEnabled(setVisible);
3463 this.showAllAlAnnotations.setEnabled(setVisible);
3464 this.hideAllAlAnnotations.setEnabled(setVisible);
3465 alignPanel.updateLayout();
3469 public void alignmentProperties()
3472 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3475 String content = MessageManager.formatMessage("label.html_content",
3477 { contents.toString() });
3480 if (Platform.isJS())
3482 JLabel textLabel = new JLabel();
3483 textLabel.setText(content);
3484 textLabel.setBackground(Color.WHITE);
3486 pane = new JPanel(new BorderLayout());
3487 ((JPanel) pane).setOpaque(true);
3488 pane.setBackground(Color.WHITE);
3489 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3498 JEditorPane editPane = new JEditorPane("text/html", "");
3499 editPane.setEditable(false);
3500 editPane.setText(content);
3504 JInternalFrame frame = new JInternalFrame();
3506 frame.getContentPane().add(new JScrollPane(pane));
3508 Desktop.addInternalFrame(frame, MessageManager
3509 .formatMessage("label.alignment_properties", new Object[]
3510 { getTitle() }), 500, 400);
3514 * Opens an Overview panel for the alignment, unless one is open already
3519 public void overviewMenuItem_actionPerformed(ActionEvent e)
3521 boolean showHiddenRegions = Cache
3522 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3523 openOverviewPanel(showHiddenRegions);
3526 public OverviewPanel openOverviewPanel(boolean showHidden)
3528 if (alignPanel.overviewPanel != null)
3530 return alignPanel.overviewPanel;
3532 JInternalFrame frame = new JInternalFrame();
3533 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3535 frame.setContentPane(overview);
3536 Desktop.addInternalFrame(frame, "", true, frame.getWidth(),
3537 frame.getHeight(), true, true);
3538 frame.setFrameIcon(null);
3540 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3541 final AlignmentPanel thePanel = this.alignPanel;
3542 frame.addInternalFrameListener(
3543 new javax.swing.event.InternalFrameAdapter()
3546 public void internalFrameClosed(
3547 javax.swing.event.InternalFrameEvent evt)
3550 thePanel.setOverviewPanel(null);
3553 if (getKeyListeners().length > 0)
3555 frame.addKeyListener(getKeyListeners()[0]);
3558 alignPanel.setOverviewPanel(overview);
3559 alignPanel.setOverviewTitle(this);
3565 public void textColour_actionPerformed()
3567 new TextColourChooser().chooseColour(alignPanel, null);
3571 * public void covariationColour_actionPerformed() {
3573 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3577 public void annotationColour_actionPerformed()
3579 new AnnotationColourChooser(viewport, alignPanel);
3583 public void annotationColumn_actionPerformed(ActionEvent e)
3585 new AnnotationColumnChooser(viewport, alignPanel);
3589 * Action on the user checking or unchecking the option to apply the selected
3590 * colour scheme to all groups. If unchecked, groups may have their own
3591 * independent colour schemes.
3596 public void applyToAllGroups_actionPerformed(boolean selected)
3598 viewport.setColourAppliesToAllGroups(selected);
3602 * Action on user selecting a colour from the colour menu
3605 * the name (not the menu item label!) of the colour scheme
3608 public void changeColour_actionPerformed(String name)
3611 * 'User Defined' opens a panel to configure or load a
3612 * user-defined colour scheme
3614 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3616 new UserDefinedColours(alignPanel);
3621 * otherwise set the chosen colour scheme (or null for 'None')
3623 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3624 viewport, viewport.getAlignment(),
3625 viewport.getHiddenRepSequences());
3630 * Actions on setting or changing the alignment colour scheme
3635 public void changeColour(ColourSchemeI cs)
3637 // TODO: pull up to controller method
3638 ColourMenuHelper.setColourSelected(colourMenu, cs);
3640 viewport.setGlobalColourScheme(cs);
3642 alignPanel.paintAlignment(true, true);
3646 * Show the PID threshold slider panel
3649 protected void modifyPID_actionPerformed()
3651 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3652 alignPanel.getViewName());
3653 SliderPanel.showPIDSlider();
3657 * Show the Conservation slider panel
3660 protected void modifyConservation_actionPerformed()
3662 SliderPanel.setConservationSlider(alignPanel,
3663 viewport.getResidueShading(), alignPanel.getViewName());
3664 SliderPanel.showConservationSlider();
3668 * Action on selecting or deselecting (Colour) By Conservation
3671 public void conservationMenuItem_actionPerformed(boolean selected)
3673 modifyConservation.setEnabled(selected);
3674 viewport.setConservationSelected(selected);
3675 viewport.getResidueShading().setConservationApplied(selected);
3677 changeColour(viewport.getGlobalColourScheme());
3680 modifyConservation_actionPerformed();
3684 SliderPanel.hideConservationSlider();
3689 * Action on selecting or deselecting (Colour) Above PID Threshold
3692 public void abovePIDThreshold_actionPerformed(boolean selected)
3694 modifyPID.setEnabled(selected);
3695 viewport.setAbovePIDThreshold(selected);
3698 viewport.getResidueShading().setThreshold(0,
3699 viewport.isIgnoreGapsConsensus());
3702 changeColour(viewport.getGlobalColourScheme());
3705 modifyPID_actionPerformed();
3709 SliderPanel.hidePIDSlider();
3720 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3722 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3723 AlignmentSorter.sortByPID(viewport.getAlignment(),
3724 viewport.getAlignment().getSequenceAt(0));
3725 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3726 viewport.getAlignment()));
3727 alignPanel.paintAlignment(true, false);
3737 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3739 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3740 AlignmentSorter.sortByID(viewport.getAlignment());
3742 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3743 alignPanel.paintAlignment(true, false);
3753 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3755 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3756 AlignmentSorter.sortByLength(viewport.getAlignment());
3757 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3758 viewport.getAlignment()));
3759 alignPanel.paintAlignment(true, false);
3769 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3771 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3772 AlignmentSorter.sortByGroup(viewport.getAlignment());
3773 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3774 viewport.getAlignment()));
3776 alignPanel.paintAlignment(true, false);
3786 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3788 new RedundancyPanel(alignPanel, this);
3798 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3800 if ((viewport.getSelectionGroup() == null)
3801 || (viewport.getSelectionGroup().getSize() < 2))
3803 JvOptionPane.showInternalMessageDialog(this,
3804 MessageManager.getString(
3805 "label.you_must_select_least_two_sequences"),
3806 MessageManager.getString("label.invalid_selection"),
3807 JvOptionPane.WARNING_MESSAGE);
3811 JInternalFrame frame = new JInternalFrame();
3812 frame.setContentPane(new PairwiseAlignPanel(viewport));
3813 Desktop.addInternalFrame(frame,
3814 MessageManager.getString("action.pairwise_alignment"), 600,
3820 public void autoCalculate_actionPerformed(ActionEvent e)
3822 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3823 if (viewport.autoCalculateConsensus)
3825 viewport.firePropertyChange("alignment", null,
3826 viewport.getAlignment().getSequences());
3831 public void sortByTreeOption_actionPerformed(ActionEvent e)
3833 viewport.sortByTree = sortByTree.isSelected();
3837 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3839 viewport.followSelection = listenToViewSelections.isSelected();
3843 * Constructs a tree panel and adds it to the desktop
3846 * tree type (NJ or AV)
3848 * name of score model used to compute the tree
3850 * parameters for the distance or similarity calculation
3852 void newTreePanel(String type, String modelName,
3853 SimilarityParamsI options)
3855 String frameTitle = "";
3858 boolean onSelection = false;
3859 if (viewport.getSelectionGroup() != null
3860 && viewport.getSelectionGroup().getSize() > 0)
3862 SequenceGroup sg = viewport.getSelectionGroup();
3864 /* Decide if the selection is a column region */
3865 for (SequenceI _s : sg.getSequences())
3867 if (_s.getLength() < sg.getEndRes())
3869 JvOptionPane.showMessageDialog(Desktop.desktop,
3870 MessageManager.getString(
3871 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3872 MessageManager.getString(
3873 "label.sequences_selection_not_aligned"),
3874 JvOptionPane.WARNING_MESSAGE);
3883 if (viewport.getAlignment().getHeight() < 2)
3889 tp = new TreePanel(alignPanel, type, modelName, options);
3890 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3892 frameTitle += " from ";
3894 if (viewport.getViewName() != null)
3896 frameTitle += viewport.getViewName() + " of ";
3899 frameTitle += this.title;
3901 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3912 public void addSortByOrderMenuItem(String title,
3913 final AlignmentOrder order)
3915 final JMenuItem item = new JMenuItem(MessageManager
3916 .formatMessage("action.by_title_param", new Object[]
3919 item.addActionListener(new java.awt.event.ActionListener()
3922 public void actionPerformed(ActionEvent e)
3924 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3926 // TODO: JBPNote - have to map order entries to curent SequenceI
3928 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3930 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3931 viewport.getAlignment()));
3933 alignPanel.paintAlignment(true, false);
3939 * Add a new sort by annotation score menu item
3942 * the menu to add the option to
3944 * the label used to retrieve scores for each sequence on the
3947 public void addSortByAnnotScoreMenuItem(JMenu sort,
3948 final String scoreLabel)
3950 final JMenuItem item = new JMenuItem(scoreLabel);
3952 item.addActionListener(new java.awt.event.ActionListener()
3955 public void actionPerformed(ActionEvent e)
3957 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3958 AlignmentSorter.sortByAnnotationScore(scoreLabel,
3959 viewport.getAlignment());// ,viewport.getSelectionGroup());
3960 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
3961 viewport.getAlignment()));
3962 alignPanel.paintAlignment(true, false);
3968 * last hash for alignment's annotation array - used to minimise cost of
3971 protected int _annotationScoreVectorHash;
3974 * search the alignment and rebuild the sort by annotation score submenu the
3975 * last alignment annotation vector hash is stored to minimize cost of
3976 * rebuilding in subsequence calls.
3980 public void buildSortByAnnotationScoresMenu()
3982 if (viewport.getAlignment().getAlignmentAnnotation() == null)
3987 if (viewport.getAlignment().getAlignmentAnnotation()
3988 .hashCode() != _annotationScoreVectorHash)
3990 sortByAnnotScore.removeAll();
3991 // almost certainly a quicker way to do this - but we keep it simple
3992 Hashtable<String, String> scoreSorts = new Hashtable<>();
3993 AlignmentAnnotation aann[];
3994 for (SequenceI sqa : viewport.getAlignment().getSequences())
3996 aann = sqa.getAnnotation();
3997 for (int i = 0; aann != null && i < aann.length; i++)
3999 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4001 scoreSorts.put(aann[i].label, aann[i].label);
4005 Enumeration<String> labels = scoreSorts.keys();
4006 while (labels.hasMoreElements())
4008 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4010 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4013 _annotationScoreVectorHash = viewport.getAlignment()
4014 .getAlignmentAnnotation().hashCode();
4019 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4020 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4021 * call. Listeners are added to remove the menu item when the treePanel is
4022 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4026 public void buildTreeSortMenu()
4028 sortByTreeMenu.removeAll();
4030 List<Component> comps = PaintRefresher.components
4031 .get(viewport.getSequenceSetId());
4032 List<TreePanel> treePanels = new ArrayList<>();
4033 for (Component comp : comps)
4035 if (comp instanceof TreePanel)
4037 treePanels.add((TreePanel) comp);
4041 if (treePanels.size() < 1)
4043 sortByTreeMenu.setVisible(false);
4047 sortByTreeMenu.setVisible(true);
4049 for (final TreePanel tp : treePanels)
4051 final JMenuItem item = new JMenuItem(tp.getTitle());
4052 item.addActionListener(new java.awt.event.ActionListener()
4055 public void actionPerformed(ActionEvent e)
4057 tp.sortByTree_actionPerformed();
4058 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4063 sortByTreeMenu.add(item);
4067 public boolean sortBy(AlignmentOrder alorder, String undoname)
4069 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4070 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4071 if (undoname != null)
4073 addHistoryItem(new OrderCommand(undoname, oldOrder,
4074 viewport.getAlignment()));
4076 alignPanel.paintAlignment(true, false);
4081 * Work out whether the whole set of sequences or just the selected set will
4082 * be submitted for multiple alignment.
4085 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4087 // Now, check we have enough sequences
4088 AlignmentView msa = null;
4090 if ((viewport.getSelectionGroup() != null)
4091 && (viewport.getSelectionGroup().getSize() > 1))
4093 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4094 // some common interface!
4096 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4097 * SequenceI[sz = seqs.getSize(false)];
4099 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4100 * seqs.getSequenceAt(i); }
4102 msa = viewport.getAlignmentView(true);
4104 else if (viewport.getSelectionGroup() != null
4105 && viewport.getSelectionGroup().getSize() == 1)
4107 int option = JvOptionPane.showConfirmDialog(this,
4108 MessageManager.getString("warn.oneseq_msainput_selection"),
4109 MessageManager.getString("label.invalid_selection"),
4110 JvOptionPane.OK_CANCEL_OPTION);
4111 if (option == JvOptionPane.OK_OPTION)
4113 msa = viewport.getAlignmentView(false);
4118 msa = viewport.getAlignmentView(false);
4124 * Decides what is submitted to a secondary structure prediction service: the
4125 * first sequence in the alignment, or in the current selection, or, if the
4126 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4127 * region or the whole alignment. (where the first sequence in the set is the
4128 * one that the prediction will be for).
4130 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4132 AlignmentView seqs = null;
4134 if ((viewport.getSelectionGroup() != null)
4135 && (viewport.getSelectionGroup().getSize() > 0))
4137 seqs = viewport.getAlignmentView(true);
4141 seqs = viewport.getAlignmentView(false);
4143 // limit sequences - JBPNote in future - could spawn multiple prediction
4145 // TODO: viewport.getAlignment().isAligned is a global state - the local
4146 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4147 if (!viewport.getAlignment().isAligned(false))
4149 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4150 // TODO: if seqs.getSequences().length>1 then should really have warned
4164 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4166 // Pick the tree file
4167 JalviewFileChooser chooser = new JalviewFileChooser(
4168 Cache.getProperty("LAST_DIRECTORY"));
4169 chooser.setFileView(new JalviewFileView());
4170 chooser.setDialogTitle(
4171 MessageManager.getString("label.select_newick_like_tree_file"));
4172 chooser.setToolTipText(
4173 MessageManager.getString("label.load_tree_file"));
4175 chooser.setResponseHandler(0, () -> {
4176 String filePath = chooser.getSelectedFile().getPath();
4177 Cache.setProperty("LAST_DIRECTORY", filePath);
4178 NewickFile fin = null;
4181 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4182 DataSourceType.FILE));
4183 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4184 } catch (Exception ex)
4186 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4187 MessageManager.getString("label.problem_reading_tree_file"),
4188 JvOptionPane.WARNING_MESSAGE);
4189 ex.printStackTrace();
4191 if (fin != null && fin.hasWarningMessage())
4193 JvOptionPane.showMessageDialog(Desktop.desktop,
4194 fin.getWarningMessage(),
4196 .getString("label.possible_problem_with_tree_file"),
4197 JvOptionPane.WARNING_MESSAGE);
4200 chooser.showOpenDialog(this);
4203 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4205 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4208 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4209 int h, int x, int y)
4211 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4215 * Add a treeviewer for the tree extracted from a Newick file object to the
4216 * current alignment view
4223 * Associated alignment input data (or null)
4232 * @return TreePanel handle
4234 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4235 AlignmentView input, int w, int h, int x, int y)
4237 TreePanel tp = null;
4243 if (nf.getTree() != null)
4245 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4251 tp.setLocation(x, y);
4254 Desktop.addInternalFrame(tp, treeTitle, w, h);
4256 } catch (Exception ex)
4258 ex.printStackTrace();
4264 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4267 int w = 400, h = 500;
4271 NewickFile fin = new NewickFile(
4272 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4273 String title = aa.label + " "
4274 + cm.getTreeMethod() + " tree" + (aa.sequenceRef != null
4275 ? (" for " + aa.sequenceRef.getDisplayId(false))
4278 showColumnWiseTree(fin, aa, title, w, h, x, y);
4279 } catch (Throwable xx)
4281 Console.error("Unexpected exception showing tree for contact matrix",
4286 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4287 String treeTitle, int w, int h, int x, int y)
4292 if (nf.getTree() == null)
4296 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4302 tp.setLocation(x, y);
4305 Desktop.addInternalFrame(tp, treeTitle, w, h);
4307 } catch (Throwable xx)
4309 Console.error("Unexpected exception showing tree for contact matrix",
4315 private boolean buildingMenu = false;
4318 * Generates menu items and listener event actions for web service clients
4321 public void BuildWebServiceMenu()
4323 while (buildingMenu)
4327 System.err.println("Waiting for building menu to finish.");
4329 } catch (Exception e)
4333 final AlignFrame me = this;
4334 buildingMenu = true;
4335 new Thread(new Runnable()
4340 final List<JMenuItem> legacyItems = new ArrayList<>();
4343 // System.err.println("Building ws menu again "
4344 // + Thread.currentThread());
4345 // TODO: add support for context dependent disabling of services based
4347 // alignment and current selection
4348 // TODO: add additional serviceHandle parameter to specify abstract
4350 // class independently of AbstractName
4351 // TODO: add in rediscovery GUI function to restart discoverer
4352 // TODO: group services by location as well as function and/or
4354 // object broker mechanism.
4355 final Vector<JMenu> wsmenu = new Vector<>();
4356 final IProgressIndicator af = me;
4359 * do not i18n these strings - they are hard-coded in class
4360 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4361 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4363 final JMenu msawsmenu = new JMenu("Alignment");
4364 final JMenu secstrmenu = new JMenu(
4365 "Secondary Structure Prediction");
4366 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4367 final JMenu analymenu = new JMenu("Analysis");
4368 final JMenu dismenu = new JMenu("Protein Disorder");
4369 // JAL-940 - only show secondary structure prediction services from
4370 // the legacy server
4371 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4373 Discoverer.services != null && (Discoverer.services.size() > 0))
4375 // TODO: refactor to allow list of AbstractName/Handler bindings to
4377 // stored or retrieved from elsewhere
4378 // No MSAWS used any more:
4379 // Vector msaws = null; // (Vector)
4380 // Discoverer.services.get("MsaWS");
4381 Vector<ServiceHandle> secstrpr = Discoverer.services
4383 if (secstrpr != null)
4385 // Add any secondary structure prediction services
4386 for (int i = 0, j = secstrpr.size(); i < j; i++)
4388 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4389 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4390 .getServiceClient(sh);
4391 int p = secstrmenu.getItemCount();
4392 impl.attachWSMenuEntry(secstrmenu, me);
4393 int q = secstrmenu.getItemCount();
4394 for (int litm = p; litm < q; litm++)
4396 legacyItems.add(secstrmenu.getItem(litm));
4402 // Add all submenus in the order they should appear on the web
4404 wsmenu.add(msawsmenu);
4405 wsmenu.add(secstrmenu);
4406 wsmenu.add(dismenu);
4407 wsmenu.add(analymenu);
4408 // No search services yet
4409 // wsmenu.add(seqsrchmenu);
4411 javax.swing.SwingUtilities.invokeLater(new Runnable()
4418 webService.removeAll();
4419 // first, add discovered services onto the webservices menu
4420 if (wsmenu.size() > 0)
4422 for (int i = 0, j = wsmenu.size(); i < j; i++)
4424 webService.add(wsmenu.get(i));
4429 webService.add(me.webServiceNoServices);
4431 // TODO: move into separate menu builder class.
4433 // logic for 2.11.1.4 is
4434 // always look to see if there is a discover. if there isn't
4435 // we can't show any Jws2 services
4436 // if there are services available, show them - regardless of
4437 // the 'show JWS2 preference'
4438 // if the discoverer is running then say so
4439 // otherwise offer to trigger discovery if 'show JWS2' is not
4441 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4442 if (jws2servs != null)
4444 if (jws2servs.hasServices())
4446 jws2servs.attachWSMenuEntry(webService, me);
4447 for (Jws2Instance sv : jws2servs.getServices())
4449 if (sv.description.toLowerCase(Locale.ROOT)
4452 for (JMenuItem jmi : legacyItems)
4454 jmi.setVisible(false);
4460 if (jws2servs.isRunning())
4462 JMenuItem tm = new JMenuItem(
4463 "Still discovering JABA Services");
4464 tm.setEnabled(false);
4467 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4469 JMenuItem enableJws2 = new JMenuItem(
4470 "Discover Web Services");
4471 enableJws2.setToolTipText(
4472 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4473 enableJws2.setEnabled(true);
4474 enableJws2.addActionListener(new ActionListener()
4478 public void actionPerformed(ActionEvent e)
4480 // start service discoverer, but ignore preference
4481 Desktop.instance.startServiceDiscovery(false,
4485 webService.add(enableJws2);
4489 build_urlServiceMenu(me.webService);
4490 build_fetchdbmenu(webService);
4491 for (JMenu item : wsmenu)
4493 if (item.getItemCount() == 0)
4495 item.setEnabled(false);
4499 item.setEnabled(true);
4502 } catch (Exception e)
4505 "Exception during web service menu building process.",
4510 } catch (Exception e)
4513 buildingMenu = false;
4520 * construct any groupURL type service menu entries.
4524 protected void build_urlServiceMenu(JMenu webService)
4526 // TODO: remove this code when 2.7 is released
4527 // DEBUG - alignmentView
4529 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4530 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4532 * @Override public void actionPerformed(ActionEvent e) {
4533 * jalview.datamodel.AlignmentView
4534 * .testSelectionViews(af.viewport.getAlignment(),
4535 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4537 * }); webService.add(testAlView);
4539 // TODO: refactor to RestClient discoverer and merge menu entries for
4540 // rest-style services with other types of analysis/calculation service
4541 // SHmmr test client - still being implemented.
4542 // DEBUG - alignmentView
4544 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4547 client.attachWSMenuEntry(
4548 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4554 * Searches the alignment sequences for xRefs and builds the Show
4555 * Cross-References menu (formerly called Show Products), with database
4556 * sources for which cross-references are found (protein sources for a
4557 * nucleotide alignment and vice versa)
4559 * @return true if Show Cross-references menu should be enabled
4561 public boolean canShowProducts()
4563 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4564 AlignmentI dataset = viewport.getAlignment().getDataset();
4566 showProducts.removeAll();
4567 final boolean dna = viewport.getAlignment().isNucleotide();
4569 if (seqs == null || seqs.length == 0)
4571 // nothing to see here.
4575 boolean showp = false;
4578 List<String> ptypes = new CrossRef(seqs, dataset)
4579 .findXrefSourcesForSequences(dna);
4581 for (final String source : ptypes)
4584 final AlignFrame af = this;
4585 JMenuItem xtype = new JMenuItem(source);
4586 xtype.addActionListener(new ActionListener()
4589 public void actionPerformed(ActionEvent e)
4591 showProductsFor(af.viewport.getSequenceSelection(), dna,
4595 showProducts.add(xtype);
4597 showProducts.setVisible(showp);
4598 showProducts.setEnabled(showp);
4599 } catch (Exception e)
4602 "canShowProducts threw an exception - please report to help@jalview.org",
4610 * Finds and displays cross-references for the selected sequences (protein
4611 * products for nucleotide sequences, dna coding sequences for peptides).
4614 * the sequences to show cross-references for
4616 * true if from a nucleotide alignment (so showing proteins)
4618 * the database to show cross-references for
4620 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4621 final String source)
4623 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4628 * Construct and display a new frame containing the translation of this
4629 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4632 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4634 AlignmentI al = null;
4637 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4639 al = dna.translateCdna(codeTable);
4640 } catch (Exception ex)
4642 Console.error("Exception during translation. Please report this !",
4644 final String msg = MessageManager.getString(
4645 "label.error_when_translating_sequences_submit_bug_report");
4646 final String errorTitle = MessageManager
4647 .getString("label.implementation_error")
4648 + MessageManager.getString("label.translation_failed");
4649 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4650 JvOptionPane.ERROR_MESSAGE);
4653 if (al == null || al.getHeight() == 0)
4655 final String msg = MessageManager.getString(
4656 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4657 final String errorTitle = MessageManager
4658 .getString("label.translation_failed");
4659 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4660 JvOptionPane.WARNING_MESSAGE);
4664 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4665 af.setFileFormat(this.currentFileFormat);
4666 final String newTitle = MessageManager
4667 .formatMessage("label.translation_of_params", new Object[]
4668 { this.getTitle(), codeTable.getId() });
4669 af.setTitle(newTitle);
4670 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4672 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4673 viewport.openSplitFrame(af, new Alignment(seqs));
4677 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4684 * Set the file format
4688 public void setFileFormat(FileFormatI format)
4690 this.currentFileFormat = format;
4694 * Try to load a features file onto the alignment.
4697 * contents or path to retrieve file or a File object
4699 * access mode of file (see jalview.io.AlignFile)
4700 * @return true if features file was parsed correctly.
4702 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4705 return avc.parseFeaturesFile(file, sourceType,
4706 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4711 public void refreshFeatureUI(boolean enableIfNecessary)
4713 // note - currently this is only still here rather than in the controller
4714 // because of the featureSettings hard reference that is yet to be
4716 if (enableIfNecessary)
4718 viewport.setShowSequenceFeatures(true);
4719 showSeqFeatures.setSelected(true);
4725 public void dragEnter(DropTargetDragEvent evt)
4730 public void dragExit(DropTargetEvent evt)
4735 public void dragOver(DropTargetDragEvent evt)
4740 public void dropActionChanged(DropTargetDragEvent evt)
4745 public void drop(DropTargetDropEvent evt)
4747 // JAL-1552 - acceptDrop required before getTransferable call for
4748 // Java's Transferable for native dnd
4749 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4750 Transferable t = evt.getTransferable();
4752 final AlignFrame thisaf = this;
4753 final List<Object> files = new ArrayList<>();
4754 List<DataSourceType> protocols = new ArrayList<>();
4758 Desktop.transferFromDropTarget(files, protocols, evt, t);
4759 } catch (Exception e)
4761 e.printStackTrace();
4765 new Thread(new Runnable()
4772 // check to see if any of these files have names matching sequences
4775 SequenceIdMatcher idm = new SequenceIdMatcher(
4776 viewport.getAlignment().getSequencesArray());
4778 * Object[] { String,SequenceI}
4780 ArrayList<Object[]> filesmatched = new ArrayList<>();
4781 ArrayList<Object> filesnotmatched = new ArrayList<>();
4782 for (int i = 0; i < files.size(); i++)
4785 Object file = files.get(i);
4786 String fileName = file.toString();
4788 DataSourceType protocol = (file instanceof File
4789 ? DataSourceType.FILE
4790 : FormatAdapter.checkProtocol(fileName));
4791 if (protocol == DataSourceType.FILE)
4794 if (file instanceof File)
4797 Platform.cacheFileData(fl);
4801 fl = new File(fileName);
4803 pdbfn = fl.getName();
4805 else if (protocol == DataSourceType.URL)
4807 URL url = new URL(fileName);
4808 pdbfn = url.getFile();
4810 if (pdbfn.length() > 0)
4812 // attempt to find a match in the alignment
4813 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4814 int l = 0, c = pdbfn.indexOf(".");
4815 while (mtch == null && c != -1)
4820 } while ((c = pdbfn.indexOf(".", l)) > l);
4823 pdbfn = pdbfn.substring(0, l);
4825 mtch = idm.findAllIdMatches(pdbfn);
4832 type = new IdentifyFile().identify(file, protocol);
4833 } catch (Exception ex)
4837 if (type != null && type.isStructureFile())
4839 filesmatched.add(new Object[] { file, protocol, mtch });
4843 // File wasn't named like one of the sequences or wasn't a PDB
4845 filesnotmatched.add(file);
4849 if (filesmatched.size() > 0)
4851 boolean autoAssociate = Cache
4852 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4855 String msg = MessageManager.formatMessage(
4856 "label.automatically_associate_structure_files_with_sequences_same_name",
4858 { Integer.valueOf(filesmatched.size())
4860 String ttl = MessageManager.getString(
4861 "label.automatically_associate_structure_files_by_name");
4862 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4863 ttl, JvOptionPane.YES_NO_OPTION);
4864 autoAssociate = choice == JvOptionPane.YES_OPTION;
4868 for (Object[] fm : filesmatched)
4870 // try and associate
4871 // TODO: may want to set a standard ID naming formalism for
4872 // associating PDB files which have no IDs.
4873 for (SequenceI toassoc : (SequenceI[]) fm[2])
4875 PDBEntry pe = new AssociatePdbFileWithSeq()
4876 .associatePdbWithSeq(fm[0].toString(),
4877 (DataSourceType) fm[1], toassoc, false,
4881 System.err.println("Associated file : "
4882 + (fm[0].toString()) + " with "
4883 + toassoc.getDisplayId(true));
4887 // TODO: do we need to update overview ? only if features are
4889 alignPanel.paintAlignment(true, false);
4895 * add declined structures as sequences
4897 for (Object[] o : filesmatched)
4899 filesnotmatched.add(o[0]);
4903 if (filesnotmatched.size() > 0)
4905 if (assocfiles > 0 && (Cache.getDefault(
4906 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4907 || JvOptionPane.showConfirmDialog(thisaf,
4908 "<html>" + MessageManager.formatMessage(
4909 "label.ignore_unmatched_dropped_files_info",
4912 filesnotmatched.size())
4915 MessageManager.getString(
4916 "label.ignore_unmatched_dropped_files"),
4917 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4921 for (Object fn : filesnotmatched)
4923 loadJalviewDataFile(fn, null, null, null);
4927 } catch (Exception ex)
4929 ex.printStackTrace();
4937 * Attempt to load a "dropped" file or URL string, by testing in turn for
4939 * <li>an Annotation file</li>
4940 * <li>a JNet file</li>
4941 * <li>a features file</li>
4942 * <li>else try to interpret as an alignment file</li>
4946 * either a filename or a URL string.
4948 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4949 FileFormatI format, SequenceI assocSeq)
4951 // BH 2018 was String file
4954 if (sourceType == null)
4956 sourceType = FormatAdapter.checkProtocol(file);
4958 // if the file isn't identified, or not positively identified as some
4959 // other filetype (PFAM is default unidentified alignment file type) then
4960 // try to parse as annotation.
4961 boolean isAnnotation = (format == null
4962 || FileFormat.Pfam.equals(format))
4963 ? new AnnotationFile().annotateAlignmentView(viewport,
4969 // first see if its a T-COFFEE score file
4970 TCoffeeScoreFile tcf = null;
4973 tcf = new TCoffeeScoreFile(file, sourceType);
4976 if (tcf.annotateAlignment(viewport.getAlignment(), true))
4980 new TCoffeeColourScheme(viewport.getAlignment()));
4981 isAnnotation = true;
4982 setStatus(MessageManager.getString(
4983 "label.successfully_pasted_tcoffee_scores_to_alignment"));
4987 // some problem - if no warning its probable that the ID matching
4988 // process didn't work
4989 JvOptionPane.showMessageDialog(Desktop.desktop,
4990 tcf.getWarningMessage() == null
4991 ? MessageManager.getString(
4992 "label.check_file_matches_sequence_ids_alignment")
4993 : tcf.getWarningMessage(),
4994 MessageManager.getString(
4995 "label.problem_reading_tcoffee_score_file"),
4996 JvOptionPane.WARNING_MESSAGE);
5003 } catch (Exception x)
5006 "Exception when processing data source as T-COFFEE score file",
5012 // try to see if its a JNet 'concise' style annotation file *before*
5014 // try to parse it as a features file
5017 format = new IdentifyFile().identify(file, sourceType);
5019 if (FileFormat.ScoreMatrix == format)
5021 ScoreMatrixFile sm = new ScoreMatrixFile(
5022 new FileParse(file, sourceType));
5024 // todo: i18n this message
5025 setStatus(MessageManager.formatMessage(
5026 "label.successfully_loaded_matrix",
5027 sm.getMatrixName()));
5029 else if (FileFormat.Jnet.equals(format))
5031 JPredFile predictions = new JPredFile(file, sourceType);
5032 new JnetAnnotationMaker();
5033 JnetAnnotationMaker.add_annotation(predictions,
5034 viewport.getAlignment(), 0, false);
5035 viewport.getAlignment().setupJPredAlignment();
5036 isAnnotation = true;
5038 // else if (IdentifyFile.FeaturesFile.equals(format))
5039 else if (FileFormat.Features.equals(format))
5041 if (parseFeaturesFile(file, sourceType))
5043 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5044 if (splitFrame != null)
5046 splitFrame.repaint();
5050 alignPanel.paintAlignment(true, true);
5056 new FileLoader().LoadFile(viewport, file, sourceType, format);
5063 alignPanel.adjustAnnotationHeight();
5064 viewport.updateSequenceIdColours();
5065 buildSortByAnnotationScoresMenu();
5066 alignPanel.paintAlignment(true, true);
5068 } catch (Exception ex)
5070 ex.printStackTrace();
5071 } catch (OutOfMemoryError oom)
5076 } catch (Exception x)
5081 + (sourceType != null
5082 ? (sourceType == DataSourceType.PASTE
5084 : "using " + sourceType + " from "
5088 ? "(parsing as '" + format + "' file)"
5090 oom, Desktop.desktop);
5095 * Method invoked by the ChangeListener on the tabbed pane, in other words
5096 * when a different tabbed pane is selected by the user or programmatically.
5099 public void tabSelectionChanged(int index)
5104 * update current Overview window title (if there is one)
5105 * to add view name "Original" if necessary
5107 alignPanel.setOverviewTitle(this);
5110 * switch panels and set Overview title (if there is one
5111 * because it was opened automatically)
5113 alignPanel = alignPanels.get(index);
5114 alignPanel.setOverviewTitle(this);
5116 viewport = alignPanel.av;
5117 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5118 setMenusFromViewport(viewport);
5119 if (featureSettings != null && featureSettings.isOpen()
5120 && featureSettings.fr.getViewport() != viewport)
5122 if (viewport.isShowSequenceFeatures())
5124 // refresh the featureSettings to reflect UI change
5125 showFeatureSettingsUI();
5129 // close feature settings for this view.
5130 featureSettings.close();
5137 * 'focus' any colour slider that is open to the selected viewport
5139 if (viewport.getConservationSelected())
5141 SliderPanel.setConservationSlider(alignPanel,
5142 viewport.getResidueShading(), alignPanel.getViewName());
5146 SliderPanel.hideConservationSlider();
5148 if (viewport.getAbovePIDThreshold())
5150 SliderPanel.setPIDSliderSource(alignPanel,
5151 viewport.getResidueShading(), alignPanel.getViewName());
5155 SliderPanel.hidePIDSlider();
5159 * If there is a frame linked to this one in a SplitPane, switch it to the
5160 * same view tab index. No infinite recursion of calls should happen, since
5161 * tabSelectionChanged() should not get invoked on setting the selected
5162 * index to an unchanged value. Guard against setting an invalid index
5163 * before the new view peer tab has been created.
5165 final AlignViewportI peer = viewport.getCodingComplement();
5168 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5169 .getAlignPanel().alignFrame;
5170 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5172 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5178 * On right mouse click on view tab, prompt for and set new view name.
5181 public void tabbedPane_mousePressed(MouseEvent e)
5183 if (e.isPopupTrigger())
5185 String msg = MessageManager.getString("label.enter_view_name");
5186 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5187 String reply = JvOptionPane.showInputDialog(msg, ttl);
5191 viewport.setViewName(reply);
5192 // TODO warn if reply is in getExistingViewNames()?
5193 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5198 public AlignViewport getCurrentView()
5204 * Open the dialog for regex description parsing.
5207 protected void extractScores_actionPerformed(ActionEvent e)
5209 ParseProperties pp = new jalview.analysis.ParseProperties(
5210 viewport.getAlignment());
5211 // TODO: verify regex and introduce GUI dialog for version 2.5
5212 // if (pp.getScoresFromDescription("col", "score column ",
5213 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5215 if (pp.getScoresFromDescription("description column",
5216 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5218 buildSortByAnnotationScoresMenu();
5226 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5230 protected void showDbRefs_actionPerformed(ActionEvent e)
5232 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5238 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5242 protected void showNpFeats_actionPerformed(ActionEvent e)
5244 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5248 * find the viewport amongst the tabs in this alignment frame and close that
5253 public boolean closeView(AlignViewportI av)
5257 this.closeMenuItem_actionPerformed(false);
5260 Component[] comp = tabbedPane.getComponents();
5261 for (int i = 0; comp != null && i < comp.length; i++)
5263 if (comp[i] instanceof AlignmentPanel)
5265 if (((AlignmentPanel) comp[i]).av == av)
5268 closeView((AlignmentPanel) comp[i]);
5276 protected void build_fetchdbmenu(JMenu webService)
5278 // Temporary hack - DBRef Fetcher always top level ws entry.
5279 // TODO We probably want to store a sequence database checklist in
5280 // preferences and have checkboxes.. rather than individual sources selected
5282 final JMenu rfetch = new JMenu(
5283 MessageManager.getString("action.fetch_db_references"));
5284 rfetch.setToolTipText(MessageManager.getString(
5285 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5286 webService.add(rfetch);
5288 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5289 MessageManager.getString("option.trim_retrieved_seqs"));
5290 trimrs.setToolTipText(
5291 MessageManager.getString("label.trim_retrieved_sequences"));
5293 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5294 trimrs.addActionListener(new ActionListener()
5297 public void actionPerformed(ActionEvent e)
5299 trimrs.setSelected(trimrs.isSelected());
5300 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5301 Boolean.valueOf(trimrs.isSelected()).toString());
5305 JMenuItem fetchr = new JMenuItem(
5306 MessageManager.getString("label.standard_databases"));
5307 fetchr.setToolTipText(
5308 MessageManager.getString("label.fetch_embl_uniprot"));
5309 fetchr.addActionListener(new ActionListener()
5313 public void actionPerformed(ActionEvent e)
5315 new Thread(new Runnable()
5320 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5321 .getAlignment().isNucleotide();
5322 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5323 alignPanel.av.getSequenceSelection(),
5324 alignPanel.alignFrame, null,
5325 alignPanel.alignFrame.featureSettings, isNucleotide);
5326 dbRefFetcher.addListener(new FetchFinishedListenerI()
5329 public void finished()
5332 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5333 .getFeatureSettingsModels())
5336 alignPanel.av.mergeFeaturesStyle(srcSettings);
5338 AlignFrame.this.setMenusForViewport();
5341 dbRefFetcher.fetchDBRefs(false);
5349 new Thread(new Runnable()
5354 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5355 .getSequenceFetcherSingleton();
5356 javax.swing.SwingUtilities.invokeLater(new Runnable()
5361 String[] dbclasses = sf.getNonAlignmentSources();
5362 List<DbSourceProxy> otherdb;
5363 JMenu dfetch = new JMenu();
5364 JMenu ifetch = new JMenu();
5365 JMenuItem fetchr = null;
5366 int comp = 0, icomp = 0, mcomp = 15;
5367 String mname = null;
5369 for (String dbclass : dbclasses)
5371 otherdb = sf.getSourceProxy(dbclass);
5372 // add a single entry for this class, or submenu allowing 'fetch
5374 if (otherdb == null || otherdb.size() < 1)
5380 mname = "From " + dbclass;
5382 if (otherdb.size() == 1)
5384 final DbSourceProxy[] dassource = otherdb
5385 .toArray(new DbSourceProxy[0]);
5386 DbSourceProxy src = otherdb.get(0);
5387 fetchr = new JMenuItem(src.getDbSource());
5388 fetchr.addActionListener(new ActionListener()
5392 public void actionPerformed(ActionEvent e)
5394 new Thread(new Runnable()
5400 boolean isNucleotide = alignPanel.alignFrame
5401 .getViewport().getAlignment()
5403 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5404 alignPanel.av.getSequenceSelection(),
5405 alignPanel.alignFrame, dassource,
5406 alignPanel.alignFrame.featureSettings,
5409 .addListener(new FetchFinishedListenerI()
5412 public void finished()
5414 FeatureSettingsModelI srcSettings = dassource[0]
5415 .getFeatureColourScheme();
5416 alignPanel.av.mergeFeaturesStyle(
5418 AlignFrame.this.setMenusForViewport();
5421 dbRefFetcher.fetchDBRefs(false);
5427 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5428 MessageManager.formatMessage(
5429 "label.fetch_retrieve_from", new Object[]
5430 { src.getDbName() })));
5436 final DbSourceProxy[] dassource = otherdb
5437 .toArray(new DbSourceProxy[0]);
5439 DbSourceProxy src = otherdb.get(0);
5440 fetchr = new JMenuItem(MessageManager
5441 .formatMessage("label.fetch_all_param", new Object[]
5442 { src.getDbSource() }));
5443 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 AlignFrame.this.setMenusForViewport();
5471 dbRefFetcher.fetchDBRefs(false);
5477 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5478 MessageManager.formatMessage(
5479 "label.fetch_retrieve_from_all_sources",
5481 { Integer.valueOf(otherdb.size())
5483 src.getDbSource(), src.getDbName() })));
5486 // and then build the rest of the individual menus
5487 ifetch = new JMenu(MessageManager.formatMessage(
5488 "label.source_from_db_source", new Object[]
5489 { src.getDbSource() }));
5491 String imname = null;
5493 for (DbSourceProxy sproxy : otherdb)
5495 String dbname = sproxy.getDbName();
5496 String sname = dbname.length() > 5
5497 ? dbname.substring(0, 5) + "..."
5499 String msname = dbname.length() > 10
5500 ? dbname.substring(0, 10) + "..."
5504 imname = MessageManager
5505 .formatMessage("label.from_msname", new Object[]
5508 fetchr = new JMenuItem(msname);
5509 final DbSourceProxy[] dassrc = { sproxy };
5510 fetchr.addActionListener(new ActionListener()
5514 public void actionPerformed(ActionEvent e)
5516 new Thread(new Runnable()
5522 boolean isNucleotide = alignPanel.alignFrame
5523 .getViewport().getAlignment()
5525 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5526 alignPanel.av.getSequenceSelection(),
5527 alignPanel.alignFrame, dassrc,
5528 alignPanel.alignFrame.featureSettings,
5531 .addListener(new FetchFinishedListenerI()
5534 public void finished()
5536 AlignFrame.this.setMenusForViewport();
5539 dbRefFetcher.fetchDBRefs(false);
5545 fetchr.setToolTipText(
5546 "<html>" + MessageManager.formatMessage(
5547 "label.fetch_retrieve_from", new Object[]
5551 if (++icomp >= mcomp || i == (otherdb.size()))
5553 ifetch.setText(MessageManager.formatMessage(
5554 "label.source_to_target", imname, sname));
5556 ifetch = new JMenu();
5564 if (comp >= mcomp || dbi >= (dbclasses.length))
5566 dfetch.setText(MessageManager.formatMessage(
5567 "label.source_to_target", mname, dbclass));
5569 dfetch = new JMenu();
5582 * Left justify the whole alignment.
5585 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5587 AlignmentI al = viewport.getAlignment();
5589 viewport.firePropertyChange("alignment", null, al);
5593 * Right justify the whole alignment.
5596 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5598 AlignmentI al = viewport.getAlignment();
5600 viewport.firePropertyChange("alignment", null, al);
5604 public void setShowSeqFeatures(boolean b)
5606 showSeqFeatures.setSelected(b);
5607 viewport.setShowSequenceFeatures(b);
5614 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5615 * awt.event.ActionEvent)
5618 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5620 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5621 alignPanel.paintAlignment(false, false);
5628 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5632 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5634 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5635 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5643 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5644 * .event.ActionEvent)
5647 protected void showGroupConservation_actionPerformed(ActionEvent e)
5649 viewport.setShowGroupConservation(showGroupConservation.getState());
5650 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5657 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5658 * .event.ActionEvent)
5661 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5663 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5664 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5671 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5672 * .event.ActionEvent)
5675 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5677 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5678 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5682 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5684 showSequenceLogo.setState(true);
5685 viewport.setShowSequenceLogo(true);
5686 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5687 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5691 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5693 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5700 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5701 * .event.ActionEvent)
5704 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5706 if (avc.makeGroupsFromSelection())
5708 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5709 alignPanel.updateAnnotation();
5710 alignPanel.paintAlignment(true,
5711 viewport.needToUpdateStructureViews());
5715 public void clearAlignmentSeqRep()
5717 // TODO refactor alignmentseqrep to controller
5718 if (viewport.getAlignment().hasSeqrep())
5720 viewport.getAlignment().setSeqrep(null);
5721 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5722 alignPanel.updateAnnotation();
5723 alignPanel.paintAlignment(true, true);
5728 protected void createGroup_actionPerformed(ActionEvent e)
5730 if (avc.createGroup())
5732 if (applyAutoAnnotationSettings.isSelected())
5734 alignPanel.updateAnnotation(true, false);
5736 alignPanel.alignmentChanged();
5741 protected void unGroup_actionPerformed(ActionEvent e)
5745 alignPanel.alignmentChanged();
5750 * make the given alignmentPanel the currently selected tab
5752 * @param alignmentPanel
5754 public void setDisplayedView(AlignmentPanel alignmentPanel)
5756 if (!viewport.getSequenceSetId()
5757 .equals(alignmentPanel.av.getSequenceSetId()))
5759 throw new Error(MessageManager.getString(
5760 "error.implementation_error_cannot_show_view_alignment_frame"));
5762 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5763 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5765 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5770 * Action on selection of menu options to Show or Hide annotations.
5773 * @param forSequences
5774 * update sequence-related annotations
5775 * @param forAlignment
5776 * update non-sequence-related annotations
5779 public void setAnnotationsVisibility(boolean visible,
5780 boolean forSequences, boolean forAlignment)
5782 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5783 .getAlignmentAnnotation();
5788 for (AlignmentAnnotation aa : anns)
5791 * don't display non-positional annotations on an alignment
5793 if (aa.annotations == null)
5797 boolean apply = (aa.sequenceRef == null && forAlignment)
5798 || (aa.sequenceRef != null && forSequences);
5801 aa.visible = visible;
5804 alignPanel.validateAnnotationDimensions(true);
5805 alignPanel.alignmentChanged();
5809 * Store selected annotation sort order for the view and repaint.
5812 protected void sortAnnotations_actionPerformed()
5814 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
5816 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
5817 alignPanel.paintAlignment(false, false);
5822 * @return alignment panels in this alignment frame
5824 public List<? extends AlignmentViewPanel> getAlignPanels()
5826 // alignPanels is never null
5827 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
5832 * Open a new alignment window, with the cDNA associated with this (protein)
5833 * alignment, aligned as is the protein.
5835 protected void viewAsCdna_actionPerformed()
5837 // TODO no longer a menu action - refactor as required
5838 final AlignmentI alignment = getViewport().getAlignment();
5839 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
5840 if (mappings == null)
5844 List<SequenceI> cdnaSeqs = new ArrayList<>();
5845 for (SequenceI aaSeq : alignment.getSequences())
5847 for (AlignedCodonFrame acf : mappings)
5849 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
5853 * There is a cDNA mapping for this protein sequence - add to new
5854 * alignment. It will share the same dataset sequence as other mapped
5855 * cDNA (no new mappings need to be created).
5857 final Sequence newSeq = new Sequence(dnaSeq);
5858 newSeq.setDatasetSequence(dnaSeq);
5859 cdnaSeqs.add(newSeq);
5863 if (cdnaSeqs.size() == 0)
5865 // show a warning dialog no mapped cDNA
5868 AlignmentI cdna = new Alignment(
5869 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
5870 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
5871 AlignFrame.DEFAULT_HEIGHT);
5872 cdna.alignAs(alignment);
5873 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
5875 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
5876 AlignFrame.DEFAULT_HEIGHT);
5880 * Set visibility of dna/protein complement view (available when shown in a
5886 protected void showComplement_actionPerformed(boolean show)
5888 SplitContainerI sf = getSplitViewContainer();
5891 sf.setComplementVisible(this, show);
5896 * Generate the reverse (optionally complemented) of the selected sequences,
5897 * and add them to the alignment
5900 protected void showReverse_actionPerformed(boolean complement)
5902 AlignmentI al = null;
5905 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
5906 al = dna.reverseCdna(complement);
5907 viewport.addAlignment(al, "");
5908 addHistoryItem(new EditCommand(
5909 MessageManager.getString("label.add_sequences"), Action.PASTE,
5910 al.getSequencesArray(), 0, al.getWidth(),
5911 viewport.getAlignment()));
5912 } catch (Exception ex)
5914 System.err.println(ex.getMessage());
5920 * Try to run a script in the Groovy console, having first ensured that this
5921 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
5922 * be targeted at this alignment.
5925 protected void runGroovy_actionPerformed()
5927 Jalview.setCurrentAlignFrame(this);
5928 groovy.ui.Console console = Desktop.getGroovyConsole();
5929 if (console != null)
5933 console.runScript();
5934 } catch (Exception ex)
5936 System.err.println((ex.toString()));
5937 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
5938 MessageManager.getString("label.couldnt_run_groovy_script"),
5939 MessageManager.getString("label.groovy_support_failed"),
5940 JvOptionPane.ERROR_MESSAGE);
5945 System.err.println("Can't run Groovy script as console not found");
5950 * Hides columns containing (or not containing) a specified feature, provided
5951 * that would not leave all columns hidden
5953 * @param featureType
5954 * @param columnsContaining
5957 public boolean hideFeatureColumns(String featureType,
5958 boolean columnsContaining)
5960 boolean notForHiding = avc.markColumnsContainingFeatures(
5961 columnsContaining, false, false, featureType);
5964 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
5965 false, featureType))
5967 getViewport().hideSelectedColumns();
5975 protected void selectHighlightedColumns_actionPerformed(
5976 ActionEvent actionEvent)
5978 // include key modifier check in case user selects from menu
5979 avc.markHighlightedColumns(
5980 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
5981 (actionEvent.getModifiers() & (ActionEvent.META_MASK
5982 | ActionEvent.CTRL_MASK)) != 0);
5986 protected void copyHighlightedColumns_actionPerformed(
5987 ActionEvent actionEvent)
5989 avc.copyHighlightedRegionsToClipboard();
5993 * Rebuilds the Colour menu, including any user-defined colours which have
5994 * been loaded either on startup or during the session
5996 public void buildColourMenu()
5998 colourMenu.removeAll();
6000 colourMenu.add(applyToAllGroups);
6001 colourMenu.add(textColour);
6002 colourMenu.addSeparator();
6004 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6005 viewport.getAlignment(), false);
6007 colourMenu.add(annotationColour);
6008 bg.add(annotationColour);
6009 colourMenu.addSeparator();
6010 colourMenu.add(conservationMenuItem);
6011 colourMenu.add(modifyConservation);
6012 colourMenu.add(abovePIDThreshold);
6013 colourMenu.add(modifyPID);
6015 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6016 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6020 * Open a dialog (if not already open) that allows the user to select and
6021 * calculate PCA or Tree analysis
6023 protected void openTreePcaDialog()
6025 if (alignPanel.getCalculationDialog() == null)
6027 new CalculationChooser(AlignFrame.this);
6032 protected void loadVcf_actionPerformed()
6034 JalviewFileChooser chooser = new JalviewFileChooser(
6035 Cache.getProperty("LAST_DIRECTORY"));
6036 chooser.setFileView(new JalviewFileView());
6037 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6038 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6039 final AlignFrame us = this;
6040 chooser.setResponseHandler(0, () -> {
6041 String choice = chooser.getSelectedFile().getPath();
6042 Cache.setProperty("LAST_DIRECTORY", choice);
6043 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6044 new VCFLoader(choice).loadVCF(seqs, us);
6046 chooser.showOpenDialog(null);
6050 private Rectangle lastFeatureSettingsBounds = null;
6053 public void setFeatureSettingsGeometry(Rectangle bounds)
6055 lastFeatureSettingsBounds = bounds;
6059 public Rectangle getFeatureSettingsGeometry()
6061 return lastFeatureSettingsBounds;
6066 class PrintThread extends Thread
6070 public PrintThread(AlignmentPanel ap)
6075 static PageFormat pf;
6080 PrinterJob printJob = PrinterJob.getPrinterJob();
6084 printJob.setPrintable(ap, pf);
6088 printJob.setPrintable(ap);
6091 if (printJob.printDialog())
6096 } catch (Exception PrintException)
6098 PrintException.printStackTrace();