2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Rectangle;
27 import java.awt.Toolkit;
28 import java.awt.datatransfer.Clipboard;
29 import java.awt.datatransfer.DataFlavor;
30 import java.awt.datatransfer.StringSelection;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.dnd.DnDConstants;
33 import java.awt.dnd.DropTargetDragEvent;
34 import java.awt.dnd.DropTargetDropEvent;
35 import java.awt.dnd.DropTargetEvent;
36 import java.awt.dnd.DropTargetListener;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseEvent;
46 import java.awt.print.PageFormat;
47 import java.awt.print.PrinterJob;
48 import java.beans.PropertyChangeEvent;
50 import java.io.FileWriter;
51 import java.io.IOException;
52 import java.io.OutputStreamWriter;
53 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Deque;
58 import java.util.Enumeration;
59 import java.util.Hashtable;
60 import java.util.List;
61 import java.util.Locale;
62 import java.util.Vector;
64 import javax.swing.AbstractButton;
65 import javax.swing.ButtonGroup;
66 import javax.swing.JCheckBoxMenuItem;
67 import javax.swing.JComponent;
68 import javax.swing.JEditorPane;
69 import javax.swing.JInternalFrame;
70 import javax.swing.JLabel;
71 import javax.swing.JLayeredPane;
72 import javax.swing.JMenu;
73 import javax.swing.JMenuItem;
74 import javax.swing.JPanel;
75 import javax.swing.JProgressBar;
76 import javax.swing.JRadioButtonMenuItem;
77 import javax.swing.JScrollPane;
78 import javax.swing.SwingUtilities;
80 import ext.vamsas.ServiceHandle;
81 import jalview.analysis.AlignmentSorter;
82 import jalview.analysis.AlignmentUtils;
83 import jalview.analysis.CrossRef;
84 import jalview.analysis.Dna;
85 import jalview.analysis.GeneticCodeI;
86 import jalview.analysis.ParseProperties;
87 import jalview.analysis.SequenceIdMatcher;
88 import jalview.api.AlignCalcWorkerI;
89 import jalview.api.AlignExportSettingsI;
90 import jalview.api.AlignViewControllerGuiI;
91 import jalview.api.AlignViewControllerI;
92 import jalview.api.AlignViewportI;
93 import jalview.api.AlignmentViewPanel;
94 import jalview.api.FeatureSettingsControllerI;
95 import jalview.api.FeatureSettingsModelI;
96 import jalview.api.SplitContainerI;
97 import jalview.api.ViewStyleI;
98 import jalview.api.analysis.SimilarityParamsI;
99 import jalview.bin.Cache;
100 import jalview.bin.Console;
101 import jalview.bin.Jalview;
102 import jalview.bin.groovy.JalviewObjectI;
103 import jalview.commands.CommandI;
104 import jalview.commands.EditCommand;
105 import jalview.commands.EditCommand.Action;
106 import jalview.commands.OrderCommand;
107 import jalview.commands.RemoveGapColCommand;
108 import jalview.commands.RemoveGapsCommand;
109 import jalview.commands.SlideSequencesCommand;
110 import jalview.commands.TrimRegionCommand;
111 import jalview.datamodel.AlignExportSettingsAdapter;
112 import jalview.datamodel.AlignedCodonFrame;
113 import jalview.datamodel.Alignment;
114 import jalview.datamodel.AlignmentAnnotation;
115 import jalview.datamodel.AlignmentExportData;
116 import jalview.datamodel.AlignmentI;
117 import jalview.datamodel.AlignmentOrder;
118 import jalview.datamodel.AlignmentView;
119 import jalview.datamodel.ColumnSelection;
120 import jalview.datamodel.ContactMatrixI;
121 import jalview.datamodel.HiddenColumns;
122 import jalview.datamodel.PDBEntry;
123 import jalview.datamodel.SeqCigar;
124 import jalview.datamodel.Sequence;
125 import jalview.datamodel.SequenceGroup;
126 import jalview.datamodel.SequenceI;
127 import jalview.gui.ColourMenuHelper.ColourChangeListener;
128 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
129 import jalview.io.AlignmentProperties;
130 import jalview.io.AnnotationFile;
131 import jalview.io.BackupFiles;
132 import jalview.io.BioJsHTMLOutput;
133 import jalview.io.DataSourceType;
134 import jalview.io.FileFormat;
135 import jalview.io.FileFormatI;
136 import jalview.io.FileFormats;
137 import jalview.io.FileLoader;
138 import jalview.io.FileParse;
139 import jalview.io.FormatAdapter;
140 import jalview.io.HtmlSvgOutput;
141 import jalview.io.IdentifyFile;
142 import jalview.io.JPredFile;
143 import jalview.io.JalviewFileChooser;
144 import jalview.io.JalviewFileView;
145 import jalview.io.JnetAnnotationMaker;
146 import jalview.io.NewickFile;
147 import jalview.io.ScoreMatrixFile;
148 import jalview.io.TCoffeeScoreFile;
149 import jalview.io.exceptions.ImageOutputException;
150 import jalview.io.vcf.VCFLoader;
151 import jalview.jbgui.GAlignFrame;
152 import jalview.project.Jalview2XML;
153 import jalview.schemes.ColourSchemeI;
154 import jalview.schemes.ColourSchemes;
155 import jalview.schemes.ResidueColourScheme;
156 import jalview.schemes.TCoffeeColourScheme;
157 import jalview.util.Constants;
158 import jalview.util.HttpUtils;
159 import jalview.util.ImageMaker.TYPE;
160 import jalview.util.MessageManager;
161 import jalview.util.Platform;
162 import jalview.util.imagemaker.BitmapImageSizing;
163 import jalview.viewmodel.AlignmentViewport;
164 import jalview.viewmodel.ViewportRanges;
165 import jalview.workers.SecondaryStructureConsensusThread;
166 import jalview.ws.DBRefFetcher;
167 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
168 import jalview.ws.jws1.Discoverer;
169 import jalview.ws.jws2.Jws2Discoverer;
170 import jalview.ws.jws2.jabaws2.Jws2Instance;
171 import jalview.ws.seqfetcher.DbSourceProxy;
177 * @version $Revision$
179 @SuppressWarnings("serial")
180 public class AlignFrame extends GAlignFrame implements DropTargetListener,
181 IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
184 public static final int DEFAULT_WIDTH = 700;
186 public static final int DEFAULT_HEIGHT = 500;
189 * The currently displayed panel (selected tabbed view if more than one)
191 public AlignmentPanel alignPanel;
193 AlignViewport viewport;
195 public AlignViewControllerI avc;
197 List<AlignmentPanel> alignPanels = new ArrayList<>();
200 * Last format used to load or save alignments in this window
202 FileFormatI currentFileFormat = null;
205 * Current filename for this alignment
207 String fileName = null;
212 * Creates a new AlignFrame object with specific width and height.
218 public AlignFrame(AlignmentI al, int width, int height)
220 this(al, null, width, height);
224 * Creates a new AlignFrame object with specific width, height and
230 * @param sequenceSetId
232 public AlignFrame(AlignmentI al, int width, int height,
233 String sequenceSetId)
235 this(al, null, width, height, sequenceSetId);
239 * Creates a new AlignFrame object with specific width, height and
245 * @param sequenceSetId
248 public AlignFrame(AlignmentI al, int width, int height,
249 String sequenceSetId, String viewId)
251 this(al, null, width, height, sequenceSetId, viewId);
255 * new alignment window with hidden columns
259 * @param hiddenColumns
260 * ColumnSelection or null
262 * Width of alignment frame
266 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
269 this(al, hiddenColumns, width, height, null);
273 * Create alignment frame for al with hiddenColumns, a specific width and
274 * height, and specific sequenceId
277 * @param hiddenColumns
280 * @param sequenceSetId
283 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
284 int height, String sequenceSetId)
286 this(al, hiddenColumns, width, height, sequenceSetId, null);
290 * Create alignment frame for al with hiddenColumns, a specific width and
291 * height, and specific sequenceId
294 * @param hiddenColumns
297 * @param sequenceSetId
302 public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
303 int height, String sequenceSetId, String viewId)
305 setSize(width, height);
307 if (al.getDataset() == null)
312 viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
314 alignPanel = new AlignmentPanel(this, viewport);
316 addAlignmentPanel(alignPanel, true);
320 public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
321 HiddenColumns hiddenColumns, int width, int height)
323 setSize(width, height);
325 if (al.getDataset() == null)
330 viewport = new AlignViewport(al, hiddenColumns);
332 if (hiddenSeqs != null && hiddenSeqs.length > 0)
334 viewport.hideSequence(hiddenSeqs);
336 alignPanel = new AlignmentPanel(this, viewport);
337 addAlignmentPanel(alignPanel, true);
342 * Make a new AlignFrame from existing alignmentPanels
349 public AlignFrame(AlignmentPanel ap)
353 addAlignmentPanel(ap, false);
358 * initalise the alignframe from the underlying viewport data and the
365 // setBackground(Color.white); // BH 2019
367 if (!Jalview.isHeadlessMode())
369 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
372 avc = new jalview.controller.AlignViewController(this, viewport,
374 if (viewport.getAlignmentConservationAnnotation() == null)
376 // BLOSUM62Colour.setEnabled(false);
377 conservationMenuItem.setEnabled(false);
378 modifyConservation.setEnabled(false);
379 // PIDColour.setEnabled(false);
380 // abovePIDThreshold.setEnabled(false);
381 // modifyPID.setEnabled(false);
384 String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
386 if (sortby.equals("Id"))
388 sortIDMenuItem_actionPerformed(null);
390 else if (sortby.equals("Pairwise Identity"))
392 sortPairwiseMenuItem_actionPerformed(null);
396 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
398 setMenusFromViewport(viewport);
399 buildSortByAnnotationScoresMenu();
400 calculateTree.addActionListener(new ActionListener()
404 public void actionPerformed(ActionEvent e)
411 if (Desktop.desktop != null)
413 this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
414 if (!Platform.isJS())
416 addServiceListeners();
421 if (viewport.getWrapAlignment())
423 wrapMenuItem_actionPerformed(null);
426 if (Cache.getDefault("SHOW_OVERVIEW", false))
428 this.overviewMenuItem_actionPerformed(null);
433 final List<AlignmentViewPanel> selviews = new ArrayList<>();
434 final List<AlignmentPanel> origview = new ArrayList<>();
435 final String menuLabel = MessageManager
436 .getString("label.copy_format_from");
437 ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
438 new ViewSetProvider()
442 public AlignmentPanel[] getAllAlignmentPanels()
445 origview.add(alignPanel);
446 // make an array of all alignment panels except for this one
447 List<AlignmentPanel> aps = new ArrayList<>(
448 Arrays.asList(Desktop.getAlignmentPanels(null)));
449 aps.remove(AlignFrame.this.alignPanel);
450 return aps.toArray(new AlignmentPanel[aps.size()]);
452 }, selviews, new ItemListener()
456 public void itemStateChanged(ItemEvent e)
458 if (origview.size() > 0)
460 final AlignmentPanel ap = origview.get(0);
463 * Copy the ViewStyle of the selected panel to 'this one'.
464 * Don't change value of 'scaleProteinAsCdna' unless copying
467 ViewStyleI vs = selviews.get(0).getAlignViewport()
469 boolean fromSplitFrame = selviews.get(0)
470 .getAlignViewport().getCodingComplement() != null;
473 vs.setScaleProteinAsCdna(ap.getAlignViewport()
474 .getViewStyle().isScaleProteinAsCdna());
476 ap.getAlignViewport().setViewStyle(vs);
479 * Also rescale ViewStyle of SplitFrame complement if there is
480 * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
481 * the whole ViewStyle (allow cDNA protein to have different
484 AlignViewportI complement = ap.getAlignViewport()
485 .getCodingComplement();
486 if (complement != null && vs.isScaleProteinAsCdna())
488 AlignFrame af = Desktop.getAlignFrameFor(complement);
489 ((SplitFrame) af.getSplitViewContainer())
491 af.setMenusForViewport();
495 ap.setSelected(true);
496 ap.alignFrame.setMenusForViewport();
501 if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
502 .indexOf("devel") > -1
503 || Cache.getDefault("VERSION", "DEVELOPMENT")
504 .toLowerCase(Locale.ROOT).indexOf("test") > -1)
506 formatMenu.add(vsel);
508 addFocusListener(new FocusAdapter()
511 public void focusGained(FocusEvent e)
513 Jalview.getInstance().setCurrentAlignFrame(AlignFrame.this);
520 * Change the filename and format for the alignment, and enable the 'reload'
521 * button functionality.
528 public void setFileName(String file, FileFormatI format)
531 setFileFormat(format);
532 reload.setEnabled(true);
536 * JavaScript will have this, maybe others. More dependable than a file name
537 * and maintains a reference to the actual bytes loaded.
541 public void setFileObject(File file)
543 this.fileObject = file;
547 * Add a KeyListener with handlers for various KeyPressed and KeyReleased
550 void addKeyListener()
552 addKeyListener(new KeyAdapter()
555 public void keyPressed(KeyEvent evt)
557 if (viewport.cursorMode
558 && ((evt.getKeyCode() >= KeyEvent.VK_0
559 && evt.getKeyCode() <= KeyEvent.VK_9)
560 || (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
561 && evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
562 && Character.isDigit(evt.getKeyChar()))
564 alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
567 switch (evt.getKeyCode())
570 case 27: // escape key
571 deselectAllSequenceMenuItem_actionPerformed(null);
575 case KeyEvent.VK_DOWN:
576 if (evt.isAltDown() || !viewport.cursorMode)
578 moveSelectedSequences(false);
580 if (viewport.cursorMode)
582 alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
587 if (evt.isAltDown() || !viewport.cursorMode)
589 moveSelectedSequences(true);
591 if (viewport.cursorMode)
593 alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
598 case KeyEvent.VK_LEFT:
599 if (evt.isAltDown() || !viewport.cursorMode)
601 slideSequences(false,
602 alignPanel.getSeqPanel().getKeyboardNo1());
606 alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
611 case KeyEvent.VK_RIGHT:
612 if (evt.isAltDown() || !viewport.cursorMode)
614 slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
618 alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
622 case KeyEvent.VK_SPACE:
623 if (viewport.cursorMode)
625 alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
626 || evt.isShiftDown() || evt.isAltDown());
630 // case KeyEvent.VK_A:
631 // if (viewport.cursorMode)
633 // alignPanel.seqPanel.insertNucAtCursor(false,"A");
634 // //jalview.bin.Console.outPrintln("A");
638 * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
639 * jalview.bin.Console.outPrintln("closing bracket"); } break;
641 case KeyEvent.VK_DELETE:
642 case KeyEvent.VK_BACK_SPACE:
643 if (!viewport.cursorMode)
645 cut_actionPerformed();
649 alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
650 || evt.isShiftDown() || evt.isAltDown());
656 if (viewport.cursorMode)
658 alignPanel.getSeqPanel().setCursorRow();
662 if (viewport.cursorMode && !evt.isControlDown())
664 alignPanel.getSeqPanel().setCursorColumn();
668 if (viewport.cursorMode)
670 alignPanel.getSeqPanel().setCursorPosition();
674 case KeyEvent.VK_ENTER:
675 case KeyEvent.VK_COMMA:
676 if (viewport.cursorMode)
678 alignPanel.getSeqPanel().setCursorRowAndColumn();
683 if (viewport.cursorMode)
685 alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
689 if (viewport.cursorMode)
691 alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
696 viewport.cursorMode = !viewport.cursorMode;
697 setStatus(MessageManager
698 .formatMessage("label.keyboard_editing_mode", new String[]
699 { (viewport.cursorMode ? "on" : "off") }));
700 if (viewport.cursorMode)
702 ViewportRanges ranges = viewport.getRanges();
703 alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
705 alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
708 alignPanel.getSeqPanel().seqCanvas.repaint();
714 Help.showHelpWindow();
715 } catch (Exception ex)
717 ex.printStackTrace();
722 boolean toggleSeqs = !evt.isControlDown();
723 boolean toggleCols = !evt.isShiftDown();
724 toggleHiddenRegions(toggleSeqs, toggleCols);
729 boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
730 boolean modifyExisting = true; // always modify, don't clear
731 // evt.isShiftDown();
732 boolean invertHighlighted = evt.isAltDown();
733 avc.markHighlightedColumns(invertHighlighted, modifyExisting,
737 case KeyEvent.VK_PAGE_UP:
738 viewport.getRanges().pageUp();
740 case KeyEvent.VK_PAGE_DOWN:
741 viewport.getRanges().pageDown();
747 public void keyReleased(KeyEvent evt)
749 switch (evt.getKeyCode())
751 case KeyEvent.VK_LEFT:
752 if (evt.isAltDown() || !viewport.cursorMode)
754 viewport.firePropertyChange("alignment", null,
755 viewport.getAlignment().getSequences());
759 case KeyEvent.VK_RIGHT:
760 if (evt.isAltDown() || !viewport.cursorMode)
762 viewport.firePropertyChange("alignment", null,
763 viewport.getAlignment().getSequences());
771 public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
773 ap.alignFrame = this;
774 avc = new jalview.controller.AlignViewController(this, viewport,
779 PaintRefresher.Register(ap, ap.av.getSequenceSetId());
781 int aSize = alignPanels.size();
783 tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
785 if (aSize == 1 && ap.av.getViewName() == null)
787 this.getContentPane().add(ap, BorderLayout.CENTER);
793 setInitialTabVisible();
796 expandViews.setEnabled(true);
797 gatherViews.setEnabled(true);
798 tabbedPane.addTab(ap.av.getViewName(), ap);
800 ap.setVisible(false);
805 if (ap.av.isPadGaps())
807 ap.av.getAlignment().padGaps();
809 ap.av.updateConservation(ap);
810 ap.av.updateConsensus(ap);
811 ap.av.updateSecondaryStructureConsensus(ap);
812 ap.av.updateStrucConsensus(ap);
816 public void setInitialTabVisible()
818 expandViews.setEnabled(true);
819 gatherViews.setEnabled(true);
820 tabbedPane.setVisible(true);
821 AlignmentPanel first = alignPanels.get(0);
822 tabbedPane.addTab(first.av.getViewName(), first);
823 this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
826 public AlignViewport getViewport()
831 /* Set up intrinsic listeners for dynamically generated GUI bits. */
832 private void addServiceListeners()
834 final java.beans.PropertyChangeListener thisListener;
835 Desktop.instance.addJalviewPropertyChangeListener("services",
836 thisListener = new java.beans.PropertyChangeListener()
839 public void propertyChange(PropertyChangeEvent evt)
841 // // jalview.bin.Console.outPrintln("Discoverer property
843 // if (evt.getPropertyName().equals("services"))
845 SwingUtilities.invokeLater(new Runnable()
851 jalview.bin.Console.errPrintln(
852 "Rebuild WS Menu for service change");
853 BuildWebServiceMenu();
860 addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
863 public void internalFrameClosed(
864 javax.swing.event.InternalFrameEvent evt)
866 // jalview.bin.Console.outPrintln("deregistering discoverer listener");
867 Desktop.instance.removeJalviewPropertyChangeListener("services",
869 closeMenuItem_actionPerformed(true);
872 // Finally, build the menu once to get current service state
873 new Thread(new Runnable()
878 BuildWebServiceMenu();
884 * Configure menu items that vary according to whether the alignment is
885 * nucleotide or protein
887 public void setGUINucleotide()
889 AlignmentI al = getViewport().getAlignment();
890 boolean nucleotide = al.isNucleotide();
892 loadVcf.setVisible(nucleotide);
893 showTranslation.setVisible(nucleotide);
894 showReverse.setVisible(nucleotide);
895 showReverseComplement.setVisible(nucleotide);
896 conservationMenuItem.setEnabled(!nucleotide);
898 .setEnabled(!nucleotide && conservationMenuItem.isSelected());
899 showGroupConservation.setEnabled(!nucleotide);
901 showComplementMenuItem
902 .setText(nucleotide ? MessageManager.getString("label.protein")
903 : MessageManager.getString("label.nucleotide"));
907 * set up menus for the current viewport. This may be called after any
908 * operation that affects the data in the current view (selection changed,
909 * etc) to update the menus to reflect the new state.
912 public void setMenusForViewport()
914 setMenusFromViewport(viewport);
918 * Need to call this method when tabs are selected for multiple views, or when
919 * loading from Jalview2XML.java
924 public void setMenusFromViewport(AlignViewport av)
926 padGapsMenuitem.setSelected(av.isPadGaps());
927 colourTextMenuItem.setSelected(av.isShowColourText());
928 abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
929 modifyPID.setEnabled(abovePIDThreshold.isSelected());
930 conservationMenuItem.setSelected(av.getConservationSelected());
931 modifyConservation.setEnabled(conservationMenuItem.isSelected());
932 seqLimits.setSelected(av.getShowJVSuffix());
933 idRightAlign.setSelected(av.isRightAlignIds());
934 centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
935 renderGapsMenuItem.setSelected(av.isRenderGaps());
936 wrapMenuItem.setSelected(av.getWrapAlignment());
937 scaleAbove.setVisible(av.getWrapAlignment());
938 scaleLeft.setVisible(av.getWrapAlignment());
939 scaleRight.setVisible(av.getWrapAlignment());
940 annotationPanelMenuItem.setState(av.isShowAnnotation());
942 * Show/hide annotations only enabled if annotation panel is shown
944 showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
945 hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
946 showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
947 hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
948 viewBoxesMenuItem.setSelected(av.getShowBoxes());
949 viewTextMenuItem.setSelected(av.getShowText());
950 showNonconservedMenuItem.setSelected(av.getShowUnconserved());
951 showGroupConsensus.setSelected(av.isShowGroupConsensus());
952 showGroupConservation.setSelected(av.isShowGroupConservation());
953 showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
954 showSequenceLogo.setSelected(av.isShowSequenceLogo());
955 normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
957 ColourMenuHelper.setColourSelected(colourMenu,
958 av.getGlobalColourScheme());
960 showSeqFeatures.setSelected(av.isShowSequenceFeatures());
961 hiddenMarkers.setState(av.getShowHiddenMarkers());
962 applyToAllGroups.setState(av.getColourAppliesToAllGroups());
963 showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
964 showDbRefsMenuitem.setSelected(av.isShowDBRefs());
965 autoCalculate.setSelected(av.autoCalculateConsensus);
966 sortByTree.setSelected(av.sortByTree);
967 listenToViewSelections.setSelected(av.followSelection);
969 showProducts.setEnabled(canShowProducts());
970 setGroovyEnabled(Desktop.getGroovyConsole() != null);
976 * Set the enabled state of the 'Run Groovy' option in the Calculate menu
980 public void setGroovyEnabled(boolean b)
982 runGroovy.setEnabled(b);
985 private IProgressIndicator progressBar;
990 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
993 public void setProgressBar(String message, long id)
995 if (!Platform.isHeadless() && progressBar != null)
996 progressBar.setProgressBar(message, id);
1000 public JProgressBar getProgressBar(long id)
1002 if (progressBar != null)
1003 return progressBar.getProgressBar(id);
1008 public void registerHandler(final long id,
1009 final IProgressIndicatorHandler handler)
1011 if (progressBar != null)
1012 progressBar.registerHandler(id, handler);
1017 * @return true if any progress bars are still active
1020 public boolean operationInProgress()
1022 return progressBar == null ? false : progressBar.operationInProgress();
1026 * Sets the text of the status bar. Note that setting a null or empty value
1027 * will cause the status bar to be hidden, with possibly undesirable flicker
1028 * of the screen layout.
1031 public void setStatus(String text)
1033 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1037 * Added so Castor Mapping file can obtain Jalview Version
1039 public String getVersion()
1041 return Cache.getProperty("VERSION");
1044 public FeatureRenderer getFeatureRenderer()
1046 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1050 public void fetchSequence_actionPerformed()
1052 new SequenceFetcher(this);
1056 public void addFromFile_actionPerformed(ActionEvent e)
1058 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1062 public void reload_actionPerformed(ActionEvent e)
1064 if (fileName != null)
1066 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1067 // originating file's format
1068 // TODO: work out how to recover feature settings for correct view(s) when
1069 // file is reloaded.
1070 if (FileFormat.Jalview.equals(currentFileFormat))
1072 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1073 for (int i = 0; i < frames.length; i++)
1075 if (frames[i] instanceof AlignFrame && frames[i] != this
1076 && ((AlignFrame) frames[i]).fileName != null
1077 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1081 frames[i].setSelected(true);
1082 Desktop.instance.closeAssociatedWindows();
1083 } catch (java.beans.PropertyVetoException ex)
1089 Desktop.instance.closeAssociatedWindows();
1091 FileLoader loader = new FileLoader();
1092 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1093 ? DataSourceType.URL
1094 : DataSourceType.FILE;
1095 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1099 Rectangle bounds = this.getBounds();
1101 FileLoader loader = new FileLoader();
1103 AlignFrame newframe = null;
1105 if (fileObject == null)
1108 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1109 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1110 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1115 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1116 DataSourceType.FILE, currentFileFormat);
1119 newframe.setBounds(bounds);
1120 if (featureSettings != null && featureSettings.isShowing())
1122 final Rectangle fspos = featureSettings.frame.getBounds();
1123 // TODO: need a 'show feature settings' function that takes bounds -
1124 // need to refactor Desktop.addFrame
1125 newframe.featureSettings_actionPerformed(null);
1126 final FeatureSettings nfs = newframe.featureSettings;
1127 SwingUtilities.invokeLater(new Runnable()
1132 nfs.frame.setBounds(fspos);
1135 this.featureSettings.close();
1136 this.featureSettings = null;
1138 this.closeMenuItem_actionPerformed(true);
1144 public void addFromText_actionPerformed(ActionEvent e)
1147 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1151 public void addFromURL_actionPerformed(ActionEvent e)
1153 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1157 public void save_actionPerformed(ActionEvent e)
1159 if (fileName == null || (currentFileFormat == null)
1160 || HttpUtils.startsWithHttpOrHttps(fileName))
1162 saveAs_actionPerformed();
1166 saveAlignment(fileName, currentFileFormat);
1171 * Saves the alignment to a file with a name chosen by the user, if necessary
1172 * warning if a file would be overwritten
1175 public void saveAs_actionPerformed()
1177 String format = currentFileFormat == null ? null
1178 : currentFileFormat.getName();
1179 JalviewFileChooser chooser = JalviewFileChooser
1180 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1182 chooser.setFileView(new JalviewFileView());
1183 chooser.setDialogTitle(
1184 MessageManager.getString("label.save_alignment_to_file"));
1185 chooser.setToolTipText(MessageManager.getString("action.save"));
1187 int value = chooser.showSaveDialog(this);
1189 if (value != JalviewFileChooser.APPROVE_OPTION)
1193 currentFileFormat = chooser.getSelectedFormat();
1194 // todo is this (2005) test now obsolete - value is never null?
1195 while (currentFileFormat == null)
1197 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1199 .getString("label.select_file_format_before_saving"),
1200 MessageManager.getString("label.file_format_not_specified"),
1201 JvOptionPane.WARNING_MESSAGE);
1202 currentFileFormat = chooser.getSelectedFormat();
1203 value = chooser.showSaveDialog(this);
1204 if (value != JalviewFileChooser.APPROVE_OPTION)
1210 fileName = chooser.getSelectedFile().getPath();
1212 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1213 Cache.setProperty("LAST_DIRECTORY", fileName);
1214 saveAlignment(fileName, currentFileFormat);
1217 boolean lastSaveSuccessful = false;
1219 FileFormatI lastFormatSaved;
1221 String lastFilenameSaved;
1224 * Raise a dialog or status message for the last call to saveAlignment.
1226 * @return true if last call to saveAlignment(file, format) was successful.
1228 public boolean isSaveAlignmentSuccessful()
1231 if (!lastSaveSuccessful)
1233 if (!Platform.isHeadless())
1235 JvOptionPane.showInternalMessageDialog(this, MessageManager
1236 .formatMessage("label.couldnt_save_file", new Object[]
1237 { lastFilenameSaved }),
1238 MessageManager.getString("label.error_saving_file"),
1239 JvOptionPane.WARNING_MESSAGE);
1243 Console.error(MessageManager
1244 .formatMessage("label.couldnt_save_file", new Object[]
1245 { lastFilenameSaved }));
1251 setStatus(MessageManager.formatMessage(
1252 "label.successfully_saved_to_file_in_format", new Object[]
1253 { lastFilenameSaved, lastFormatSaved }));
1256 return lastSaveSuccessful;
1260 * Saves the alignment to the specified file path, in the specified format,
1261 * which may be an alignment format, or Jalview project format. If the
1262 * alignment has hidden regions, or the format is one capable of including
1263 * non-sequence data (features, annotations, groups), then the user may be
1264 * prompted to specify what to include in the output.
1269 public void saveAlignment(String file, FileFormatI format)
1271 saveAlignment(file, format, false, false);
1274 public void saveAlignment(String file, FileFormatI format, boolean stdout,
1275 boolean forceBackup)
1277 lastSaveSuccessful = true;
1280 lastFilenameSaved = file;
1282 lastFormatSaved = format;
1284 if (FileFormat.Jalview.equals(format))
1286 String shortName = title;
1287 if (shortName.indexOf(File.separatorChar) > -1)
1289 shortName = shortName
1290 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1292 // TODO deal with stdout=true
1293 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1296 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1297 if (lastSaveSuccessful)
1299 this.getViewport().setSavedUpToDate(true);
1302 statusBar.setText(MessageManager.formatMessage(
1303 "label.successfully_saved_to_file_in_format", new Object[]
1309 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1310 Runnable cancelAction = () -> {
1311 lastSaveSuccessful = false;
1313 Runnable outputAction = () -> {
1314 // todo defer this to inside formatSequences (or later)
1315 AlignmentExportData exportData = viewport.getAlignExportData(options);
1316 String output = new FormatAdapter(alignPanel, options)
1317 .formatSequences(format, exportData.getAlignment(),
1318 exportData.getOmitHidden(),
1319 exportData.getStartEndPostions(),
1320 viewport.getAlignment().getHiddenColumns());
1323 lastSaveSuccessful = false;
1327 // create backupfiles object and get new temp filename destination
1328 boolean doBackup = forceBackup
1329 || (BackupFiles.getEnabled() && !stdout);
1330 BackupFiles backupfiles = null;
1333 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1334 backupfiles = new BackupFiles(file);
1338 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1340 Console.trace("ALIGNFRAME setting PrintWriter");
1341 PrintWriter out = stdout
1342 ? new PrintWriter(new OutputStreamWriter(System.out))
1343 : new PrintWriter(new FileWriter(tempFilePath));
1345 if (backupfiles != null)
1347 Console.trace("ALIGNFRAME about to write to temp file "
1348 + backupfiles.getTempFilePath());
1355 Console.trace("ALIGNFRAME about to close file");
1357 Console.trace("ALIGNFRAME closed file");
1359 AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
1362 statusBar.setText(MessageManager.formatMessage(
1363 "label.successfully_printed_to_stdout_in_format",
1365 { format.getName() }));
1369 statusBar.setText(MessageManager.formatMessage(
1370 "label.successfully_saved_to_file_in_format",
1372 { fileName, format.getName() }));
1374 lastSaveSuccessful = true;
1375 } catch (IOException e)
1377 lastSaveSuccessful = false;
1379 "ALIGNFRAME Something happened writing the temp file");
1380 Console.error(e.getMessage());
1381 Console.debug(Cache.getStackTraceString(e));
1382 } catch (Exception ex)
1384 lastSaveSuccessful = false;
1386 "ALIGNFRAME Something unexpected happened writing the temp file");
1387 Console.error(ex.getMessage());
1388 Console.debug(Cache.getStackTraceString(ex));
1393 backupfiles.setWriteSuccess(lastSaveSuccessful);
1394 Console.debug("ALIGNFRAME writing temp file was "
1395 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1396 // do the backup file roll and rename the temp file to actual file
1397 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1398 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1399 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1400 + (lastSaveSuccessful ? "" : "un") + "successfully");
1403 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1404 if (lastSaveSuccessful)
1406 AlignFrame.this.getViewport().setSavedUpToDate(true);
1412 * show dialog with export options if applicable; else just do it
1414 if (AlignExportOptions.isNeeded(viewport, format))
1416 AlignExportOptions choices = new AlignExportOptions(
1417 alignPanel.getAlignViewport(), format, options);
1418 choices.setResponseAction(0, outputAction);
1419 choices.setResponseAction(1, cancelAction);
1420 choices.showDialog();
1427 } catch (Exception e)
1429 // TODO Auto-generated catch block
1430 e.printStackTrace();
1436 * Outputs the alignment to textbox in the requested format, if necessary
1437 * first prompting the user for whether to include hidden regions or
1440 * @param fileFormatName
1443 protected void outputText_actionPerformed(String fileFormatName)
1445 FileFormatI fileFormat = FileFormats.getInstance()
1446 .forName(fileFormatName);
1447 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1448 Runnable outputAction = () -> {
1449 // todo defer this to inside formatSequences (or later)
1450 AlignmentExportData exportData = viewport.getAlignExportData(options);
1451 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1452 cap.setForInput(null);
1455 FileFormatI format = fileFormat;
1456 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1457 format, exportData.getAlignment(),
1458 exportData.getOmitHidden(),
1459 exportData.getStartEndPostions(),
1460 viewport.getAlignment().getHiddenColumns()));
1461 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1462 "label.alignment_output_command", new Object[]
1463 { fileFormat.getName() }), 600, 500);
1464 } catch (OutOfMemoryError oom)
1466 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1473 * show dialog with export options if applicable; else just do it
1475 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1477 AlignExportOptions choices = new AlignExportOptions(
1478 alignPanel.getAlignViewport(), fileFormat, options);
1479 choices.setResponseAction(0, outputAction);
1480 choices.showDialog();
1487 } catch (Exception e)
1489 e.printStackTrace();
1501 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1503 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1506 htmlSVG.exportHTML(null);
1507 } catch (ImageOutputException x)
1509 // report problem to console and raise dialog
1514 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1516 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1519 bjs.exportHTML(null);
1520 } catch (ImageOutputException x)
1522 // report problem to console and raise dialog
1526 public void createImageMap(File file, String image)
1530 alignPanel.makePNGImageMap(file, image);
1531 } catch (ImageOutputException x)
1533 // report problem to console and raise dialog
1538 public void createPNG_actionPerformed(ActionEvent e)
1543 } catch (ImageOutputException ioex)
1545 // raise dialog, and report via console
1550 public void createEPS_actionPerformed(ActionEvent e)
1555 } catch (ImageOutputException ioex)
1557 // raise dialog, and report via console
1563 public void createSVG_actionPerformed(ActionEvent e)
1568 } catch (ImageOutputException ioex)
1570 // raise dialog, and report via console
1576 * Creates a PNG image of the alignment and writes it to the given file. If
1577 * the file is null, the user is prompted to choose a file.
1581 public void createPNG(File f) throws ImageOutputException
1583 createPNG(f, null, BitmapImageSizing.defaultBitmapImageSizing());
1586 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1587 throws ImageOutputException
1589 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1593 * Creates an EPS image of the alignment and writes it to the given file. If
1594 * the file is null, the user is prompted to choose a file.
1598 public void createEPS(File f) throws ImageOutputException
1603 public void createEPS(File f, String renderer) throws ImageOutputException
1605 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1609 * Creates an SVG image of the alignment and writes it to the given file. If
1610 * the file is null, the user is prompted to choose a file.
1614 public void createSVG(File f) throws ImageOutputException
1619 public void createSVG(File f, String renderer) throws ImageOutputException
1621 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1625 public void pageSetup_actionPerformed(ActionEvent e)
1627 PrinterJob printJob = PrinterJob.getPrinterJob();
1628 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1638 public void printMenuItem_actionPerformed(ActionEvent e)
1640 // Putting in a thread avoids Swing painting problems
1641 PrintThread thread = new PrintThread(alignPanel);
1646 public void exportFeatures_actionPerformed(ActionEvent e)
1648 new AnnotationExporter(alignPanel).exportFeatures();
1652 public void exportAnnotations_actionPerformed(ActionEvent e)
1654 new AnnotationExporter(alignPanel).exportAnnotations();
1658 public void associatedData_actionPerformed(ActionEvent e)
1660 final JalviewFileChooser chooser = new JalviewFileChooser(
1661 Cache.getProperty("LAST_DIRECTORY"));
1662 chooser.setFileView(new JalviewFileView());
1663 String tooltip = MessageManager
1664 .getString("label.load_jalview_annotations");
1665 chooser.setDialogTitle(tooltip);
1666 chooser.setToolTipText(tooltip);
1667 chooser.setResponseHandler(0, () -> {
1668 String choice = chooser.getSelectedFile().getPath();
1669 Cache.setProperty("LAST_DIRECTORY", choice);
1670 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1673 chooser.showOpenDialog(this);
1677 * Close the current view or all views in the alignment frame. If the frame
1678 * only contains one view then the alignment will be removed from memory.
1680 * @param closeAllTabs
1683 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1685 if (alignPanels != null && alignPanels.size() < 2)
1687 closeAllTabs = true;
1690 Desktop.closeModal(this);
1694 if (alignPanels != null)
1698 if (this.isClosed())
1700 // really close all the windows - otherwise wait till
1701 // setClosed(true) is called
1702 for (int i = 0; i < alignPanels.size(); i++)
1704 AlignmentPanel ap = alignPanels.get(i);
1711 closeView(alignPanel);
1716 if (featureSettings != null && featureSettings.isOpen())
1718 featureSettings.close();
1719 featureSettings = null;
1723 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1724 * be called recursively, with the frame now in 'closed' state
1726 this.setClosed(true);
1728 } catch (Exception ex)
1730 ex.printStackTrace();
1735 * Close the specified panel and close up tabs appropriately.
1737 * @param panelToClose
1739 public void closeView(AlignmentPanel panelToClose)
1741 int index = tabbedPane.getSelectedIndex();
1742 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1743 alignPanels.remove(panelToClose);
1744 panelToClose.closePanel();
1745 panelToClose = null;
1747 tabbedPane.removeTabAt(closedindex);
1748 tabbedPane.validate();
1750 if (index > closedindex || index == tabbedPane.getTabCount())
1752 // modify currently selected tab index if necessary.
1756 this.tabSelectionChanged(index);
1762 void updateEditMenuBar()
1765 if (viewport.getHistoryList().size() > 0)
1767 undoMenuItem.setEnabled(true);
1768 CommandI command = viewport.getHistoryList().peek();
1769 undoMenuItem.setText(MessageManager
1770 .formatMessage("label.undo_command", new Object[]
1771 { command.getDescription() }));
1775 undoMenuItem.setEnabled(false);
1776 undoMenuItem.setText(MessageManager.getString("action.undo"));
1779 if (viewport.getRedoList().size() > 0)
1781 redoMenuItem.setEnabled(true);
1783 CommandI command = viewport.getRedoList().peek();
1784 redoMenuItem.setText(MessageManager
1785 .formatMessage("label.redo_command", new Object[]
1786 { command.getDescription() }));
1790 redoMenuItem.setEnabled(false);
1791 redoMenuItem.setText(MessageManager.getString("action.redo"));
1796 public void addHistoryItem(CommandI command)
1798 if (command.getSize() > 0)
1800 viewport.addToHistoryList(command);
1801 viewport.clearRedoList();
1802 updateEditMenuBar();
1803 viewport.updateHiddenColumns();
1804 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1805 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1806 // viewport.getColumnSelection()
1807 // .getHiddenColumns().size() > 0);
1813 * @return alignment objects for all views
1815 public AlignmentI[] getViewAlignments()
1817 if (alignPanels != null)
1819 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1821 for (AlignmentPanel ap : alignPanels)
1823 als[i++] = ap.av.getAlignment();
1827 if (viewport != null)
1829 return new AlignmentI[] { viewport.getAlignment() };
1841 protected void undoMenuItem_actionPerformed(ActionEvent e)
1843 if (viewport.getHistoryList().isEmpty())
1847 CommandI command = viewport.getHistoryList().pop();
1848 viewport.addToRedoList(command);
1849 command.undoCommand(getViewAlignments());
1851 AlignmentViewport originalSource = getOriginatingSource(command);
1852 updateEditMenuBar();
1854 if (originalSource != null)
1856 if (originalSource != viewport)
1859 "Implementation worry: mismatch of viewport origin for undo");
1861 originalSource.updateHiddenColumns();
1862 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1864 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1865 // viewport.getColumnSelection()
1866 // .getHiddenColumns().size() > 0);
1867 originalSource.firePropertyChange("alignment", null,
1868 originalSource.getAlignment().getSequences());
1879 protected void redoMenuItem_actionPerformed(ActionEvent e)
1881 if (viewport.getRedoList().size() < 1)
1886 CommandI command = viewport.getRedoList().pop();
1887 viewport.addToHistoryList(command);
1888 command.doCommand(getViewAlignments());
1890 AlignmentViewport originalSource = getOriginatingSource(command);
1891 updateEditMenuBar();
1893 if (originalSource != null)
1896 if (originalSource != viewport)
1899 "Implementation worry: mismatch of viewport origin for redo");
1901 originalSource.updateHiddenColumns();
1902 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1904 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1905 // viewport.getColumnSelection()
1906 // .getHiddenColumns().size() > 0);
1907 originalSource.firePropertyChange("alignment", null,
1908 originalSource.getAlignment().getSequences());
1912 AlignmentViewport getOriginatingSource(CommandI command)
1914 AlignmentViewport originalSource = null;
1915 // For sequence removal and addition, we need to fire
1916 // the property change event FROM the viewport where the
1917 // original alignment was altered
1918 AlignmentI al = null;
1919 if (command instanceof EditCommand)
1921 EditCommand editCommand = (EditCommand) command;
1922 al = editCommand.getAlignment();
1923 List<Component> comps = PaintRefresher.components
1924 .get(viewport.getSequenceSetId());
1926 for (Component comp : comps)
1928 if (comp instanceof AlignmentPanel)
1930 if (al == ((AlignmentPanel) comp).av.getAlignment())
1932 originalSource = ((AlignmentPanel) comp).av;
1939 if (originalSource == null)
1941 // The original view is closed, we must validate
1942 // the current view against the closed view first
1945 PaintRefresher.validateSequences(al, viewport.getAlignment());
1948 originalSource = viewport;
1951 return originalSource;
1955 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1956 * or the sequence under cursor in keyboard mode
1961 public void moveSelectedSequences(boolean up)
1963 SequenceGroup sg = viewport.getSelectionGroup();
1967 if (viewport.cursorMode)
1969 sg = new SequenceGroup();
1970 sg.addSequence(viewport.getAlignment().getSequenceAt(
1971 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1979 if (sg.getSize() < 1)
1984 // TODO: JAL-3733 - add an event to the undo buffer for this !
1986 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1987 viewport.getHiddenRepSequences(), up);
1988 alignPanel.paintAlignment(true, false);
1991 synchronized void slideSequences(boolean right, int size)
1993 List<SequenceI> sg = new ArrayList<>();
1994 if (viewport.cursorMode)
1996 sg.add(viewport.getAlignment()
1997 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1999 else if (viewport.getSelectionGroup() != null
2000 && viewport.getSelectionGroup().getSize() != viewport
2001 .getAlignment().getHeight())
2003 sg = viewport.getSelectionGroup()
2004 .getSequences(viewport.getHiddenRepSequences());
2012 List<SequenceI> invertGroup = new ArrayList<>();
2014 for (SequenceI seq : viewport.getAlignment().getSequences())
2016 if (!sg.contains(seq))
2018 invertGroup.add(seq);
2022 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
2024 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2025 for (int i = 0; i < invertGroup.size(); i++)
2027 seqs2[i] = invertGroup.get(i);
2030 SlideSequencesCommand ssc;
2033 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2034 viewport.getGapCharacter());
2038 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2039 viewport.getGapCharacter());
2042 int groupAdjustment = 0;
2043 if (ssc.getGapsInsertedBegin() && right)
2045 if (viewport.cursorMode)
2047 alignPanel.getSeqPanel().moveCursor(size, 0);
2051 groupAdjustment = size;
2054 else if (!ssc.getGapsInsertedBegin() && !right)
2056 if (viewport.cursorMode)
2058 alignPanel.getSeqPanel().moveCursor(-size, 0);
2062 groupAdjustment = -size;
2066 if (groupAdjustment != 0)
2068 viewport.getSelectionGroup().setStartRes(
2069 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2070 viewport.getSelectionGroup().setEndRes(
2071 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2075 * just extend the last slide command if compatible; but not if in
2076 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2078 boolean appendHistoryItem = false;
2079 Deque<CommandI> historyList = viewport.getHistoryList();
2080 boolean inSplitFrame = getSplitViewContainer() != null;
2081 if (!inSplitFrame && historyList != null && historyList.size() > 0
2082 && historyList.peek() instanceof SlideSequencesCommand)
2084 appendHistoryItem = ssc.appendSlideCommand(
2085 (SlideSequencesCommand) historyList.peek());
2088 if (!appendHistoryItem)
2090 addHistoryItem(ssc);
2103 protected void copy_actionPerformed()
2105 if (viewport.getSelectionGroup() == null)
2109 // TODO: preserve the ordering of displayed alignment annotation in any
2110 // internal paste (particularly sequence associated annotation)
2111 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2112 String[] omitHidden = null;
2114 if (viewport.hasHiddenColumns())
2116 omitHidden = viewport.getViewAsString(true);
2119 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2120 seqs, omitHidden, null);
2122 StringSelection ss = new StringSelection(output);
2126 jalview.gui.Desktop.internalCopy = true;
2127 // Its really worth setting the clipboard contents
2128 // to empty before setting the large StringSelection!!
2129 Toolkit.getDefaultToolkit().getSystemClipboard()
2130 .setContents(new StringSelection(""), null);
2132 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2134 } catch (OutOfMemoryError er)
2136 new OOMWarning("copying region", er);
2140 HiddenColumns hiddenColumns = null;
2141 if (viewport.hasHiddenColumns())
2143 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2144 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2146 // create new HiddenColumns object with copy of hidden regions
2147 // between startRes and endRes, offset by startRes
2148 hiddenColumns = new HiddenColumns(
2149 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2150 hiddenCutoff, hiddenOffset);
2153 Desktop.jalviewClipboard = new Object[] { seqs,
2154 viewport.getAlignment().getDataset(), hiddenColumns };
2155 setStatus(MessageManager.formatMessage(
2156 "label.copied_sequences_to_clipboard", new Object[]
2157 { Integer.valueOf(seqs.length).toString() }));
2167 protected void pasteNew_actionPerformed(ActionEvent e)
2179 protected void pasteThis_actionPerformed(ActionEvent e)
2185 * Paste contents of Jalview clipboard
2187 * @param newAlignment
2188 * true to paste to a new alignment, otherwise add to this.
2190 void paste(boolean newAlignment)
2192 boolean externalPaste = true;
2195 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2196 Transferable contents = c.getContents(this);
2198 if (contents == null)
2207 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2208 if (str.length() < 1)
2213 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2215 } catch (OutOfMemoryError er)
2217 new OOMWarning("Out of memory pasting sequences!!", er);
2221 SequenceI[] sequences;
2222 boolean annotationAdded = false;
2223 AlignmentI alignment = null;
2225 if (Desktop.jalviewClipboard != null)
2227 // The clipboard was filled from within Jalview, we must use the
2229 // And dataset from the copied alignment
2230 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2231 // be doubly sure that we create *new* sequence objects.
2232 sequences = new SequenceI[newseq.length];
2233 for (int i = 0; i < newseq.length; i++)
2235 sequences[i] = new Sequence(newseq[i]);
2237 alignment = new Alignment(sequences);
2238 externalPaste = false;
2242 // parse the clipboard as an alignment.
2243 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2245 sequences = alignment.getSequencesArray();
2249 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2255 if (Desktop.jalviewClipboard != null)
2257 // dataset is inherited
2258 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2262 // new dataset is constructed
2263 alignment.setDataset(null);
2265 alwidth = alignment.getWidth() + 1;
2269 AlignmentI pastedal = alignment; // preserve pasted alignment object
2270 // Add pasted sequences and dataset into existing alignment.
2271 alignment = viewport.getAlignment();
2272 alwidth = alignment.getWidth() + 1;
2273 // decide if we need to import sequences from an existing dataset
2274 boolean importDs = Desktop.jalviewClipboard != null
2275 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2276 // importDs==true instructs us to copy over new dataset sequences from
2277 // an existing alignment
2278 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2280 // minimum dataset set
2282 for (int i = 0; i < sequences.length; i++)
2286 newDs.addElement(null);
2288 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2290 if (importDs && ds != null)
2292 if (!newDs.contains(ds))
2294 newDs.setElementAt(ds, i);
2295 ds = new Sequence(ds);
2296 // update with new dataset sequence
2297 sequences[i].setDatasetSequence(ds);
2301 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2306 // copy and derive new dataset sequence
2307 sequences[i] = sequences[i].deriveSequence();
2308 alignment.getDataset()
2309 .addSequence(sequences[i].getDatasetSequence());
2310 // TODO: avoid creation of duplicate dataset sequences with a
2311 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2313 alignment.addSequence(sequences[i]); // merges dataset
2317 newDs.clear(); // tidy up
2319 if (alignment.getAlignmentAnnotation() != null)
2321 for (AlignmentAnnotation alan : alignment
2322 .getAlignmentAnnotation())
2324 if (alan.graphGroup > fgroup)
2326 fgroup = alan.graphGroup;
2330 if (pastedal.getAlignmentAnnotation() != null)
2332 // Add any annotation attached to alignment.
2333 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2334 for (int i = 0; i < alann.length; i++)
2336 annotationAdded = true;
2337 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2339 AlignmentAnnotation newann = new AlignmentAnnotation(
2341 if (newann.graphGroup > -1)
2343 if (newGraphGroups.size() <= newann.graphGroup
2344 || newGraphGroups.get(newann.graphGroup) == null)
2346 for (int q = newGraphGroups
2347 .size(); q <= newann.graphGroup; q++)
2349 newGraphGroups.add(q, null);
2351 newGraphGroups.set(newann.graphGroup,
2352 Integer.valueOf(++fgroup));
2354 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2358 newann.padAnnotation(alwidth);
2359 alignment.addAnnotation(newann);
2369 addHistoryItem(new EditCommand(
2370 MessageManager.getString("label.add_sequences"),
2371 Action.PASTE, sequences, 0, alignment.getWidth(),
2374 // Add any annotations attached to sequences
2375 for (int i = 0; i < sequences.length; i++)
2377 if (sequences[i].getAnnotation() != null)
2379 AlignmentAnnotation newann;
2380 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2382 annotationAdded = true;
2383 newann = sequences[i].getAnnotation()[a];
2384 newann.adjustForAlignment();
2385 newann.padAnnotation(alwidth);
2386 if (newann.graphGroup > -1)
2388 if (newann.graphGroup > -1)
2390 if (newGraphGroups.size() <= newann.graphGroup
2391 || newGraphGroups.get(newann.graphGroup) == null)
2393 for (int q = newGraphGroups
2394 .size(); q <= newann.graphGroup; q++)
2396 newGraphGroups.add(q, null);
2398 newGraphGroups.set(newann.graphGroup,
2399 Integer.valueOf(++fgroup));
2401 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2405 // annotation was duplicated earlier
2406 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2407 // take care of contact matrix too
2408 ContactMatrixI cm = sequences[i]
2409 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2412 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2416 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2424 // propagate alignment changed.
2425 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2426 if (annotationAdded)
2428 // Duplicate sequence annotation in all views.
2429 AlignmentI[] alview = this.getViewAlignments();
2430 for (int i = 0; i < sequences.length; i++)
2432 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2437 for (int avnum = 0; avnum < alview.length; avnum++)
2439 if (alview[avnum] != alignment)
2441 // duplicate in a view other than the one with input focus
2442 int avwidth = alview[avnum].getWidth() + 1;
2443 // this relies on sann being preserved after we
2444 // modify the sequence's annotation array for each duplication
2445 for (int a = 0; a < sann.length; a++)
2447 AlignmentAnnotation newann = new AlignmentAnnotation(
2449 sequences[i].addAlignmentAnnotation(newann);
2450 newann.padAnnotation(avwidth);
2451 alview[avnum].addAnnotation(newann); // annotation was
2452 // duplicated earlier
2453 // TODO JAL-1145 graphGroups are not updated for sequence
2454 // annotation added to several views. This may cause
2456 alview[avnum].setAnnotationIndex(newann, a);
2461 buildSortByAnnotationScoresMenu();
2463 viewport.firePropertyChange("alignment", null,
2464 alignment.getSequences());
2465 if (alignPanels != null)
2467 for (AlignmentPanel ap : alignPanels)
2469 ap.validateAnnotationDimensions(false);
2474 alignPanel.validateAnnotationDimensions(false);
2480 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2482 String newtitle = new String("Copied sequences");
2484 if (Desktop.jalviewClipboard != null
2485 && Desktop.jalviewClipboard[2] != null)
2487 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2488 af.viewport.setHiddenColumns(hc);
2491 // >>>This is a fix for the moment, until a better solution is
2493 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2494 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2495 .getFeatureRenderer());
2497 // TODO: maintain provenance of an alignment, rather than just make the
2498 // title a concatenation of operations.
2501 if (title.startsWith("Copied sequences"))
2507 newtitle = newtitle.concat("- from " + title);
2512 newtitle = new String("Pasted sequences");
2515 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2520 } catch (Exception ex)
2522 ex.printStackTrace();
2523 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2524 // could be anything being pasted in here
2530 protected void expand_newalign(ActionEvent e)
2534 AlignmentI alignment = AlignmentUtils
2535 .expandContext(getViewport().getAlignment(), -1);
2536 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2538 String newtitle = new String("Flanking alignment");
2540 if (Desktop.jalviewClipboard != null
2541 && Desktop.jalviewClipboard[2] != null)
2543 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2544 af.viewport.setHiddenColumns(hc);
2547 // >>>This is a fix for the moment, until a better solution is
2549 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2550 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2551 .getFeatureRenderer());
2553 // TODO: maintain provenance of an alignment, rather than just make the
2554 // title a concatenation of operations.
2556 if (title.startsWith("Copied sequences"))
2562 newtitle = newtitle.concat("- from " + title);
2566 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2568 } catch (Exception ex)
2570 ex.printStackTrace();
2571 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2572 // could be anything being pasted in here
2573 } catch (OutOfMemoryError oom)
2575 new OOMWarning("Viewing flanking region of alignment", oom);
2580 * Action Cut (delete and copy) the selected region
2583 protected void cut_actionPerformed()
2585 copy_actionPerformed();
2586 delete_actionPerformed();
2590 * Performs menu option to Delete the currently selected region
2593 protected void delete_actionPerformed()
2596 SequenceGroup sg = viewport.getSelectionGroup();
2602 Runnable okAction = () -> {
2603 SequenceI[] cut = sg.getSequences()
2604 .toArray(new SequenceI[sg.getSize()]);
2606 addHistoryItem(new EditCommand(
2607 MessageManager.getString("label.cut_sequences"), Action.CUT,
2608 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2609 viewport.getAlignment()));
2611 viewport.setSelectionGroup(null);
2612 viewport.sendSelection();
2613 viewport.getAlignment().deleteGroup(sg);
2615 viewport.firePropertyChange("alignment", null,
2616 viewport.getAlignment().getSequences());
2617 if (viewport.getAlignment().getHeight() < 1)
2621 AlignFrame.this.setClosed(true);
2622 } catch (Exception ex)
2629 * If the cut affects all sequences, prompt for confirmation
2631 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2633 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2634 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2635 if (wholeHeight && wholeWidth)
2637 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2638 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2639 Object[] options = new Object[] {
2640 MessageManager.getString("action.ok"),
2641 MessageManager.getString("action.cancel") };
2642 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2643 MessageManager.getString("label.delete_all"),
2644 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2645 options, options[0]);
2652 } catch (Exception e)
2654 e.printStackTrace();
2666 protected void deleteGroups_actionPerformed(ActionEvent e)
2668 if (avc.deleteGroups())
2670 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2671 alignPanel.updateAnnotation();
2672 alignPanel.paintAlignment(true, true);
2683 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2685 SequenceGroup sg = new SequenceGroup(
2686 viewport.getAlignment().getSequences());
2688 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2689 viewport.setSelectionGroup(sg);
2690 viewport.isSelectionGroupChanged(true);
2691 viewport.sendSelection();
2692 // JAL-2034 - should delegate to
2693 // alignPanel to decide if overview needs
2695 alignPanel.paintAlignment(false, false);
2696 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2706 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2708 if (viewport.cursorMode)
2710 alignPanel.getSeqPanel().keyboardNo1 = null;
2711 alignPanel.getSeqPanel().keyboardNo2 = null;
2713 viewport.setSelectionGroup(null);
2714 viewport.getColumnSelection().clear();
2715 viewport.setSearchResults(null);
2716 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2717 // JAL-2034 - should delegate to
2718 // alignPanel to decide if overview needs
2720 alignPanel.paintAlignment(false, false);
2721 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2722 viewport.sendSelection();
2732 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2734 SequenceGroup sg = viewport.getSelectionGroup();
2738 selectAllSequenceMenuItem_actionPerformed(null);
2743 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2745 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2747 // JAL-2034 - should delegate to
2748 // alignPanel to decide if overview needs
2751 alignPanel.paintAlignment(true, false);
2752 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2753 viewport.sendSelection();
2757 public void invertColSel_actionPerformed(ActionEvent e)
2759 viewport.invertColumnSelection();
2760 alignPanel.paintAlignment(true, false);
2761 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2762 viewport.sendSelection();
2772 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2774 trimAlignment(true);
2784 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2786 trimAlignment(false);
2789 void trimAlignment(boolean trimLeft)
2791 ColumnSelection colSel = viewport.getColumnSelection();
2794 if (!colSel.isEmpty())
2798 column = colSel.getMin();
2802 column = colSel.getMax();
2806 if (viewport.getSelectionGroup() != null)
2808 seqs = viewport.getSelectionGroup()
2809 .getSequencesAsArray(viewport.getHiddenRepSequences());
2813 seqs = viewport.getAlignment().getSequencesArray();
2816 TrimRegionCommand trimRegion;
2819 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2820 column, viewport.getAlignment());
2821 viewport.getRanges().setStartRes(0);
2825 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2826 column, viewport.getAlignment());
2829 setStatus(MessageManager.formatMessage("label.removed_columns",
2831 { Integer.valueOf(trimRegion.getSize()).toString() }));
2833 addHistoryItem(trimRegion);
2835 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2837 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2838 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2840 viewport.getAlignment().deleteGroup(sg);
2844 viewport.firePropertyChange("alignment", null,
2845 viewport.getAlignment().getSequences());
2856 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2858 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2861 if (viewport.getSelectionGroup() != null)
2863 seqs = viewport.getSelectionGroup()
2864 .getSequencesAsArray(viewport.getHiddenRepSequences());
2865 start = viewport.getSelectionGroup().getStartRes();
2866 end = viewport.getSelectionGroup().getEndRes();
2870 seqs = viewport.getAlignment().getSequencesArray();
2873 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2874 "Remove Gapped Columns", seqs, start, end,
2875 viewport.getAlignment());
2877 addHistoryItem(removeGapCols);
2879 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2881 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2883 // This is to maintain viewport position on first residue
2884 // of first sequence
2885 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2886 ViewportRanges ranges = viewport.getRanges();
2887 int startRes = seq.findPosition(ranges.getStartRes());
2888 // ShiftList shifts;
2889 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2890 // edit.alColumnChanges=shifts.getInverse();
2891 // if (viewport.hasHiddenColumns)
2892 // viewport.getColumnSelection().compensateForEdits(shifts);
2893 ranges.setStartRes(seq.findIndex(startRes) - 1);
2894 viewport.firePropertyChange("alignment", null,
2895 viewport.getAlignment().getSequences());
2906 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2908 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2911 if (viewport.getSelectionGroup() != null)
2913 seqs = viewport.getSelectionGroup()
2914 .getSequencesAsArray(viewport.getHiddenRepSequences());
2915 start = viewport.getSelectionGroup().getStartRes();
2916 end = viewport.getSelectionGroup().getEndRes();
2920 seqs = viewport.getAlignment().getSequencesArray();
2923 // This is to maintain viewport position on first residue
2924 // of first sequence
2925 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2926 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2928 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2929 viewport.getAlignment()));
2931 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2933 viewport.firePropertyChange("alignment", null,
2934 viewport.getAlignment().getSequences());
2945 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2947 viewport.setPadGaps(padGapsMenuitem.isSelected());
2948 viewport.firePropertyChange("alignment", null,
2949 viewport.getAlignment().getSequences());
2953 * Opens a Finder dialog
2958 public void findMenuItem_actionPerformed(ActionEvent e)
2960 new Finder(alignPanel, false, null);
2964 * Create a new view of the current alignment.
2967 public void newView_actionPerformed(ActionEvent e)
2969 newView(null, true);
2973 * Creates and shows a new view of the current alignment.
2976 * title of newly created view; if null, one will be generated
2977 * @param copyAnnotation
2978 * if true then duplicate all annnotation, groups and settings
2979 * @return new alignment panel, already displayed.
2981 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2984 * Create a new AlignmentPanel (with its own, new Viewport)
2986 AlignmentPanel newap = new jalview.project.Jalview2XML()
2987 .copyAlignPanel(alignPanel);
2988 if (!copyAnnotation)
2991 * remove all groups and annotation except for the automatic stuff
2993 newap.av.getAlignment().deleteAllGroups();
2994 newap.av.getAlignment().deleteAllAnnotations(false);
2997 newap.av.setGatherViewsHere(false);
2999 if (viewport.getViewName() == null)
3001 viewport.setViewName(
3002 MessageManager.getString("label.view_name_original"));
3006 * Views share the same edits undo and redo stacks
3008 newap.av.setHistoryList(viewport.getHistoryList());
3009 newap.av.setRedoList(viewport.getRedoList());
3012 * copy any visualisation settings that are not saved in the project
3014 newap.av.setColourAppliesToAllGroups(
3015 viewport.getColourAppliesToAllGroups());
3018 * Views share the same mappings; need to deregister any new mappings
3019 * created by copyAlignPanel, and register the new reference to the shared
3022 newap.av.replaceMappings(viewport.getAlignment());
3025 * start up cDNA consensus (if applicable) now mappings are in place
3027 if (newap.av.initComplementConsensus())
3029 newap.refresh(true); // adjust layout of annotations
3032 newap.av.setViewName(getNewViewName(viewTitle));
3034 addAlignmentPanel(newap, true);
3035 newap.alignmentChanged();
3037 if (alignPanels.size() == 2)
3039 viewport.setGatherViewsHere(true);
3041 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3047 * Make a new name for the view, ensuring it is unique within the current
3048 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3049 * these now use viewId. Unique view names are still desirable for usability.)
3054 protected String getNewViewName(String viewTitle)
3056 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3057 boolean addFirstIndex = false;
3058 if (viewTitle == null || viewTitle.trim().length() == 0)
3060 viewTitle = MessageManager.getString("action.view");
3061 addFirstIndex = true;
3065 index = 1;// we count from 1 if given a specific name
3067 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3069 List<Component> comps = PaintRefresher.components
3070 .get(viewport.getSequenceSetId());
3072 List<String> existingNames = getExistingViewNames(comps);
3074 while (existingNames.contains(newViewName))
3076 newViewName = viewTitle + " " + (++index);
3082 * Returns a list of distinct view names found in the given list of
3083 * components. View names are held on the viewport of an AlignmentPanel.
3088 protected List<String> getExistingViewNames(List<Component> comps)
3090 List<String> existingNames = new ArrayList<>();
3091 for (Component comp : comps)
3093 if (comp instanceof AlignmentPanel)
3095 AlignmentPanel ap = (AlignmentPanel) comp;
3096 if (!existingNames.contains(ap.av.getViewName()))
3098 existingNames.add(ap.av.getViewName());
3102 return existingNames;
3106 * Explode tabbed views into separate windows.
3109 public void expandViews_actionPerformed(ActionEvent e)
3111 Desktop.explodeViews(this);
3115 * Gather views in separate windows back into a tabbed presentation.
3118 public void gatherViews_actionPerformed(ActionEvent e)
3120 Desktop.instance.gatherViews(this);
3130 public void font_actionPerformed(ActionEvent e)
3132 new FontChooser(alignPanel);
3142 protected void seqLimit_actionPerformed(ActionEvent e)
3144 viewport.setShowJVSuffix(seqLimits.isSelected());
3146 alignPanel.getIdPanel().getIdCanvas()
3147 .setPreferredSize(alignPanel.calculateIdWidth());
3148 alignPanel.paintAlignment(true, false);
3152 public void idRightAlign_actionPerformed(ActionEvent e)
3154 viewport.setRightAlignIds(idRightAlign.isSelected());
3155 alignPanel.paintAlignment(false, false);
3159 public void centreColumnLabels_actionPerformed(ActionEvent e)
3161 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3162 alignPanel.paintAlignment(false, false);
3168 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3171 protected void followHighlight_actionPerformed()
3174 * Set the 'follow' flag on the Viewport (and scroll to position if now
3177 final boolean state = this.followHighlightMenuItem.getState();
3178 viewport.setFollowHighlight(state);
3181 alignPanel.scrollToPosition(viewport.getSearchResults());
3192 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3194 viewport.setColourText(colourTextMenuItem.isSelected());
3195 alignPanel.paintAlignment(false, false);
3205 public void wrapMenuItem_actionPerformed(ActionEvent e)
3207 setWrapFormat(wrapMenuItem.isSelected(), false);
3210 public void setWrapFormat(boolean b, boolean setMenuItem)
3212 scaleAbove.setVisible(b);
3213 scaleLeft.setVisible(b);
3214 scaleRight.setVisible(b);
3215 viewport.setWrapAlignment(b);
3216 alignPanel.updateLayout();
3219 wrapMenuItem.setSelected(b);
3224 public void showAllSeqs_actionPerformed(ActionEvent e)
3226 viewport.showAllHiddenSeqs();
3230 public void showAllColumns_actionPerformed(ActionEvent e)
3232 viewport.showAllHiddenColumns();
3233 alignPanel.paintAlignment(true, true);
3234 viewport.sendSelection();
3238 public void hideSelSequences_actionPerformed(ActionEvent e)
3240 viewport.hideAllSelectedSeqs();
3244 * called by key handler and the hide all/show all menu items
3249 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3252 boolean hide = false;
3253 SequenceGroup sg = viewport.getSelectionGroup();
3254 if (!toggleSeqs && !toggleCols)
3256 // Hide everything by the current selection - this is a hack - we do the
3257 // invert and then hide
3258 // first check that there will be visible columns after the invert.
3259 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3260 && sg.getStartRes() <= sg.getEndRes()))
3262 // now invert the sequence set, if required - empty selection implies
3263 // that no hiding is required.
3266 invertSequenceMenuItem_actionPerformed(null);
3267 sg = viewport.getSelectionGroup();
3271 viewport.expandColSelection(sg, true);
3272 // finally invert the column selection and get the new sequence
3274 invertColSel_actionPerformed(null);
3281 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3283 hideSelSequences_actionPerformed(null);
3286 else if (!(toggleCols && viewport.hasSelectedColumns()))
3288 showAllSeqs_actionPerformed(null);
3294 if (viewport.hasSelectedColumns())
3296 hideSelColumns_actionPerformed(null);
3299 viewport.setSelectionGroup(sg);
3304 showAllColumns_actionPerformed(null);
3313 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3314 * event.ActionEvent)
3317 public void hideAllButSelection_actionPerformed(ActionEvent e)
3319 toggleHiddenRegions(false, false);
3320 viewport.sendSelection();
3327 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3331 public void hideAllSelection_actionPerformed(ActionEvent e)
3333 SequenceGroup sg = viewport.getSelectionGroup();
3334 viewport.expandColSelection(sg, false);
3335 viewport.hideAllSelectedSeqs();
3336 viewport.hideSelectedColumns();
3337 alignPanel.updateLayout();
3338 alignPanel.paintAlignment(true, true);
3339 viewport.sendSelection();
3346 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3350 public void showAllhidden_actionPerformed(ActionEvent e)
3352 viewport.showAllHiddenColumns();
3353 viewport.showAllHiddenSeqs();
3354 alignPanel.paintAlignment(true, true);
3355 viewport.sendSelection();
3359 public void hideSelColumns_actionPerformed(ActionEvent e)
3361 viewport.hideSelectedColumns();
3362 alignPanel.updateLayout();
3363 alignPanel.paintAlignment(true, true);
3364 viewport.sendSelection();
3368 public void hiddenMarkers_actionPerformed(ActionEvent e)
3370 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3381 protected void scaleAbove_actionPerformed(ActionEvent e)
3383 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3384 alignPanel.updateLayout();
3385 alignPanel.paintAlignment(true, false);
3395 protected void scaleLeft_actionPerformed(ActionEvent e)
3397 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3398 alignPanel.updateLayout();
3399 alignPanel.paintAlignment(true, false);
3409 protected void scaleRight_actionPerformed(ActionEvent e)
3411 viewport.setScaleRightWrapped(scaleRight.isSelected());
3412 alignPanel.updateLayout();
3413 alignPanel.paintAlignment(true, false);
3423 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3425 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3426 alignPanel.paintAlignment(false, false);
3436 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3438 viewport.setShowText(viewTextMenuItem.isSelected());
3439 alignPanel.paintAlignment(false, false);
3449 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3451 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3452 alignPanel.paintAlignment(false, false);
3455 public FeatureSettings featureSettings;
3458 public FeatureSettingsControllerI getFeatureSettingsUI()
3460 return featureSettings;
3464 public void featureSettings_actionPerformed(ActionEvent e)
3466 showFeatureSettingsUI();
3470 public FeatureSettingsControllerI showFeatureSettingsUI()
3472 if (featureSettings != null)
3474 featureSettings.closeOldSettings();
3475 featureSettings = null;
3477 if (!showSeqFeatures.isSelected())
3479 // make sure features are actually displayed
3480 showSeqFeatures.setSelected(true);
3481 showSeqFeatures_actionPerformed(null);
3483 featureSettings = new FeatureSettings(this);
3484 return featureSettings;
3488 * Set or clear 'Show Sequence Features'
3494 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3496 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3497 alignPanel.paintAlignment(true, true);
3501 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3502 * the annotations panel as a whole.
3504 * The options to show/hide all annotations should be enabled when the panel
3505 * is shown, and disabled when the panel is hidden.
3510 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3512 final boolean setVisible = annotationPanelMenuItem.isSelected();
3513 viewport.setShowAnnotation(setVisible);
3514 this.showAllSeqAnnotations.setEnabled(setVisible);
3515 this.hideAllSeqAnnotations.setEnabled(setVisible);
3516 this.showAllAlAnnotations.setEnabled(setVisible);
3517 this.hideAllAlAnnotations.setEnabled(setVisible);
3518 alignPanel.updateLayout();
3522 public void alignmentProperties()
3525 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3528 String content = MessageManager.formatMessage("label.html_content",
3530 { contents.toString() });
3533 if (Platform.isJS())
3535 JLabel textLabel = new JLabel();
3536 textLabel.setText(content);
3537 textLabel.setBackground(Color.WHITE);
3539 pane = new JPanel(new BorderLayout());
3540 ((JPanel) pane).setOpaque(true);
3541 pane.setBackground(Color.WHITE);
3542 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3551 JEditorPane editPane = new JEditorPane("text/html", "");
3552 editPane.setEditable(false);
3553 editPane.setText(content);
3557 JInternalFrame frame = new JInternalFrame();
3558 frame.setFrameIcon(null);
3559 frame.getContentPane().add(new JScrollPane(pane));
3561 Desktop.addInternalFrame(frame, MessageManager
3562 .formatMessage("label.alignment_properties", new Object[]
3563 { getTitle() }), 500, 400);
3567 * Opens an Overview panel for the alignment, unless one is open already
3572 public void overviewMenuItem_actionPerformed(ActionEvent e)
3574 boolean showHiddenRegions = Cache
3575 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3576 openOverviewPanel(showHiddenRegions);
3579 public OverviewPanel openOverviewPanel(boolean showHidden)
3581 if (alignPanel.overviewPanel != null)
3583 return alignPanel.overviewPanel;
3585 JInternalFrame frame = new JInternalFrame();
3586 frame.setFrameIcon(null);
3587 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3589 frame.setContentPane(overview);
3591 alignPanel.setOverviewPanel(overview);
3592 alignPanel.setOverviewTitle(this);
3594 Desktop.addInternalFrame(frame, overview.getTitle(), true,
3595 frame.getWidth(), frame.getHeight(), true, true);
3597 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3598 final AlignmentPanel thePanel = this.alignPanel;
3599 frame.addInternalFrameListener(
3600 new javax.swing.event.InternalFrameAdapter()
3603 public void internalFrameClosed(
3604 javax.swing.event.InternalFrameEvent evt)
3607 thePanel.setOverviewPanel(null);
3610 if (getKeyListeners().length > 0)
3612 frame.addKeyListener(getKeyListeners()[0]);
3619 public void textColour_actionPerformed()
3621 new TextColourChooser().chooseColour(alignPanel, null);
3625 * public void covariationColour_actionPerformed() {
3627 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3631 public void annotationColour_actionPerformed()
3633 new AnnotationColourChooser(viewport, alignPanel);
3637 public void annotationColumn_actionPerformed(ActionEvent e)
3639 new AnnotationColumnChooser(viewport, alignPanel);
3643 * Action on the user checking or unchecking the option to apply the selected
3644 * colour scheme to all groups. If unchecked, groups may have their own
3645 * independent colour schemes.
3650 public void applyToAllGroups_actionPerformed(boolean selected)
3652 viewport.setColourAppliesToAllGroups(selected);
3656 * Action on user selecting a colour from the colour menu
3659 * the name (not the menu item label!) of the colour scheme
3662 public void changeColour_actionPerformed(String name)
3665 * 'User Defined' opens a panel to configure or load a
3666 * user-defined colour scheme
3668 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3670 new UserDefinedColours(alignPanel);
3675 * otherwise set the chosen colour scheme (or null for 'None')
3677 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3678 viewport, viewport.getAlignment(),
3679 viewport.getHiddenRepSequences());
3684 * Actions on setting or changing the alignment colour scheme
3689 public void changeColour(ColourSchemeI cs)
3691 // TODO: pull up to controller method
3692 ColourMenuHelper.setColourSelected(colourMenu, cs);
3694 viewport.setGlobalColourScheme(cs);
3696 alignPanel.paintAlignment(true, true);
3700 * Show the PID threshold slider panel
3703 protected void modifyPID_actionPerformed()
3705 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3706 alignPanel.getViewName());
3707 SliderPanel.showPIDSlider();
3711 * Show the Conservation slider panel
3714 protected void modifyConservation_actionPerformed()
3716 SliderPanel.setConservationSlider(alignPanel,
3717 viewport.getResidueShading(), alignPanel.getViewName());
3718 SliderPanel.showConservationSlider();
3722 * Action on selecting or deselecting (Colour) By Conservation
3725 public void conservationMenuItem_actionPerformed(boolean selected)
3727 modifyConservation.setEnabled(selected);
3728 viewport.setConservationSelected(selected);
3729 viewport.getResidueShading().setConservationApplied(selected);
3731 changeColour(viewport.getGlobalColourScheme());
3734 modifyConservation_actionPerformed();
3738 SliderPanel.hideConservationSlider();
3743 * Action on selecting or deselecting (Colour) Above PID Threshold
3746 public void abovePIDThreshold_actionPerformed(boolean selected)
3748 modifyPID.setEnabled(selected);
3749 viewport.setAbovePIDThreshold(selected);
3752 viewport.getResidueShading().setThreshold(0,
3753 viewport.isIgnoreGapsConsensus());
3756 changeColour(viewport.getGlobalColourScheme());
3759 modifyPID_actionPerformed();
3763 SliderPanel.hidePIDSlider();
3774 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3776 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3777 AlignmentSorter.sortByPID(viewport.getAlignment(),
3778 viewport.getAlignment().getSequenceAt(0));
3779 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3780 viewport.getAlignment()));
3781 alignPanel.paintAlignment(true, false);
3791 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3793 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3794 AlignmentSorter.sortByID(viewport.getAlignment());
3796 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3797 alignPanel.paintAlignment(true, false);
3807 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3809 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3810 AlignmentSorter.sortByLength(viewport.getAlignment());
3811 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3812 viewport.getAlignment()));
3813 alignPanel.paintAlignment(true, false);
3823 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3825 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3826 AlignmentSorter.sortByGroup(viewport.getAlignment());
3827 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3828 viewport.getAlignment()));
3830 alignPanel.paintAlignment(true, false);
3840 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3842 new RedundancyPanel(alignPanel, this);
3852 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3854 if ((viewport.getSelectionGroup() == null)
3855 || (viewport.getSelectionGroup().getSize() < 2))
3857 JvOptionPane.showInternalMessageDialog(this,
3858 MessageManager.getString(
3859 "label.you_must_select_least_two_sequences"),
3860 MessageManager.getString("label.invalid_selection"),
3861 JvOptionPane.WARNING_MESSAGE);
3865 JInternalFrame frame = new JInternalFrame();
3866 frame.setFrameIcon(null);
3867 frame.setContentPane(new PairwiseAlignPanel(viewport));
3868 Desktop.addInternalFrame(frame,
3869 MessageManager.getString("action.pairwise_alignment"), 600,
3875 public void autoCalculate_actionPerformed(ActionEvent e)
3877 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3878 if (viewport.autoCalculateConsensus)
3880 viewport.firePropertyChange("alignment", null,
3881 viewport.getAlignment().getSequences());
3886 public void sortByTreeOption_actionPerformed(ActionEvent e)
3888 viewport.sortByTree = sortByTree.isSelected();
3892 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3894 viewport.followSelection = listenToViewSelections.isSelected();
3898 * Constructs a tree panel and adds it to the desktop
3901 * tree type (NJ or AV)
3903 * name of score model used to compute the tree
3905 * parameters for the distance or similarity calculation
3907 void newTreePanel(String type, String modelName,
3908 SimilarityParamsI options)
3910 String frameTitle = "";
3913 boolean onSelection = false;
3914 if (viewport.getSelectionGroup() != null
3915 && viewport.getSelectionGroup().getSize() > 0)
3917 SequenceGroup sg = viewport.getSelectionGroup();
3919 /* Decide if the selection is a column region */
3920 for (SequenceI _s : sg.getSequences())
3922 if (_s.getLength() < sg.getEndRes())
3924 JvOptionPane.showMessageDialog(Desktop.desktop,
3925 MessageManager.getString(
3926 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3927 MessageManager.getString(
3928 "label.sequences_selection_not_aligned"),
3929 JvOptionPane.WARNING_MESSAGE);
3938 if (viewport.getAlignment().getHeight() < 2)
3944 tp = new TreePanel(alignPanel, type, modelName, options);
3945 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3947 frameTitle += " from ";
3949 if (viewport.getViewName() != null)
3951 frameTitle += viewport.getViewName() + " of ";
3954 frameTitle += this.title;
3956 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3967 public void addSortByOrderMenuItem(String title,
3968 final AlignmentOrder order)
3970 final JMenuItem item = new JMenuItem(MessageManager
3971 .formatMessage("action.by_title_param", new Object[]
3974 item.addActionListener(new java.awt.event.ActionListener()
3977 public void actionPerformed(ActionEvent e)
3979 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3981 // TODO: JBPNote - have to map order entries to curent SequenceI
3983 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3985 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3986 viewport.getAlignment()));
3988 alignPanel.paintAlignment(true, false);
3994 * Add a new sort by annotation score menu item
3997 * the menu to add the option to
3999 * the label used to retrieve scores for each sequence on the
4002 public void addSortByAnnotScoreMenuItem(JMenu sort,
4003 final String scoreLabel)
4005 final JMenuItem item = new JMenuItem(scoreLabel);
4007 item.addActionListener(new java.awt.event.ActionListener()
4010 public void actionPerformed(ActionEvent e)
4012 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4013 AlignmentSorter.sortByAnnotationScore(scoreLabel,
4014 viewport.getAlignment());// ,viewport.getSelectionGroup());
4015 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
4016 viewport.getAlignment()));
4017 alignPanel.paintAlignment(true, false);
4023 * last hash for alignment's annotation array - used to minimise cost of
4026 protected int _annotationScoreVectorHash;
4029 * search the alignment and rebuild the sort by annotation score submenu the
4030 * last alignment annotation vector hash is stored to minimize cost of
4031 * rebuilding in subsequence calls.
4035 public void buildSortByAnnotationScoresMenu()
4037 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4042 if (viewport.getAlignment().getAlignmentAnnotation()
4043 .hashCode() != _annotationScoreVectorHash)
4045 sortByAnnotScore.removeAll();
4046 // almost certainly a quicker way to do this - but we keep it simple
4047 Hashtable<String, String> scoreSorts = new Hashtable<>();
4048 AlignmentAnnotation aann[];
4049 for (SequenceI sqa : viewport.getAlignment().getSequences())
4051 aann = sqa.getAnnotation();
4052 for (int i = 0; aann != null && i < aann.length; i++)
4054 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4056 scoreSorts.put(aann[i].label, aann[i].label);
4060 Enumeration<String> labels = scoreSorts.keys();
4061 while (labels.hasMoreElements())
4063 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4065 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4068 _annotationScoreVectorHash = viewport.getAlignment()
4069 .getAlignmentAnnotation().hashCode();
4074 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4075 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4076 * call. Listeners are added to remove the menu item when the treePanel is
4077 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4081 public void buildTreeSortMenu()
4083 sortByTreeMenu.removeAll();
4085 List<Component> comps = PaintRefresher.components
4086 .get(viewport.getSequenceSetId());
4087 List<TreePanel> treePanels = new ArrayList<>();
4088 for (Component comp : comps)
4090 if (comp instanceof TreePanel)
4092 treePanels.add((TreePanel) comp);
4096 if (treePanels.size() < 1)
4098 sortByTreeMenu.setVisible(false);
4102 sortByTreeMenu.setVisible(true);
4104 for (final TreePanel tp : treePanels)
4106 final JMenuItem item = new JMenuItem(tp.getTitle());
4107 item.addActionListener(new java.awt.event.ActionListener()
4110 public void actionPerformed(ActionEvent e)
4112 tp.sortByTree_actionPerformed();
4113 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4118 sortByTreeMenu.add(item);
4122 public boolean sortBy(AlignmentOrder alorder, String undoname)
4124 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4125 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4126 if (undoname != null)
4128 addHistoryItem(new OrderCommand(undoname, oldOrder,
4129 viewport.getAlignment()));
4131 alignPanel.paintAlignment(true, false);
4136 * Work out whether the whole set of sequences or just the selected set will
4137 * be submitted for multiple alignment.
4140 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4142 // Now, check we have enough sequences
4143 AlignmentView msa = null;
4145 if ((viewport.getSelectionGroup() != null)
4146 && (viewport.getSelectionGroup().getSize() > 1))
4148 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4149 // some common interface!
4151 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4152 * SequenceI[sz = seqs.getSize(false)];
4154 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4155 * seqs.getSequenceAt(i); }
4157 msa = viewport.getAlignmentView(true);
4159 else if (viewport.getSelectionGroup() != null
4160 && viewport.getSelectionGroup().getSize() == 1)
4162 int option = JvOptionPane.showConfirmDialog(this,
4163 MessageManager.getString("warn.oneseq_msainput_selection"),
4164 MessageManager.getString("label.invalid_selection"),
4165 JvOptionPane.OK_CANCEL_OPTION);
4166 if (option == JvOptionPane.OK_OPTION)
4168 msa = viewport.getAlignmentView(false);
4173 msa = viewport.getAlignmentView(false);
4179 * Decides what is submitted to a secondary structure prediction service: the
4180 * first sequence in the alignment, or in the current selection, or, if the
4181 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4182 * region or the whole alignment. (where the first sequence in the set is the
4183 * one that the prediction will be for).
4185 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4187 AlignmentView seqs = null;
4189 if ((viewport.getSelectionGroup() != null)
4190 && (viewport.getSelectionGroup().getSize() > 0))
4192 seqs = viewport.getAlignmentView(true);
4196 seqs = viewport.getAlignmentView(false);
4198 // limit sequences - JBPNote in future - could spawn multiple prediction
4200 // TODO: viewport.getAlignment().isAligned is a global state - the local
4201 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4202 if (!viewport.getAlignment().isAligned(false))
4204 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4205 // TODO: if seqs.getSequences().length>1 then should really have warned
4219 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4221 // Pick the tree file
4222 JalviewFileChooser chooser = new JalviewFileChooser(
4223 Cache.getProperty("LAST_DIRECTORY"));
4224 chooser.setFileView(new JalviewFileView());
4225 chooser.setDialogTitle(
4226 MessageManager.getString("label.select_newick_like_tree_file"));
4227 chooser.setToolTipText(
4228 MessageManager.getString("label.load_tree_file"));
4230 chooser.setResponseHandler(0, () -> {
4231 String filePath = chooser.getSelectedFile().getPath();
4232 Cache.setProperty("LAST_DIRECTORY", filePath);
4233 NewickFile fin = null;
4236 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4237 DataSourceType.FILE));
4238 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4239 } catch (Exception ex)
4241 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4242 MessageManager.getString("label.problem_reading_tree_file"),
4243 JvOptionPane.WARNING_MESSAGE);
4244 ex.printStackTrace();
4246 if (fin != null && fin.hasWarningMessage())
4248 JvOptionPane.showMessageDialog(Desktop.desktop,
4249 fin.getWarningMessage(),
4251 .getString("label.possible_problem_with_tree_file"),
4252 JvOptionPane.WARNING_MESSAGE);
4255 chooser.showOpenDialog(this);
4258 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4260 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4263 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4264 int h, int x, int y)
4266 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4270 * Add a treeviewer for the tree extracted from a Newick file object to the
4271 * current alignment view
4278 * Associated alignment input data (or null)
4287 * @return TreePanel handle
4289 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4290 AlignmentView input, int w, int h, int x, int y)
4292 TreePanel tp = null;
4298 if (nf.getTree() != null)
4300 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4306 tp.setLocation(x, y);
4309 Desktop.addInternalFrame(tp, treeTitle, w, h);
4311 } catch (Exception ex)
4313 ex.printStackTrace();
4319 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4322 int w = 400, h = 500;
4326 NewickFile fin = new NewickFile(
4327 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4328 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4329 + (aa.sequenceRef != null
4330 ? (" for " + aa.sequenceRef.getDisplayId(false))
4333 showColumnWiseTree(fin, aa, title, w, h, x, y);
4334 } catch (Throwable xx)
4336 Console.error("Unexpected exception showing tree for contact matrix",
4341 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4342 String treeTitle, int w, int h, int x, int y)
4347 if (nf.getTree() == null)
4351 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4357 tp.setLocation(x, y);
4360 Desktop.addInternalFrame(tp, treeTitle, w, h);
4362 } catch (Throwable xx)
4364 Console.error("Unexpected exception showing tree for contact matrix",
4370 private boolean buildingMenu = false;
4373 * Generates menu items and listener event actions for web service clients
4376 public void BuildWebServiceMenu()
4378 while (buildingMenu)
4383 .errPrintln("Waiting for building menu to finish.");
4385 } catch (Exception e)
4389 final AlignFrame me = this;
4390 buildingMenu = true;
4391 new Thread(new Runnable()
4396 final List<JMenuItem> legacyItems = new ArrayList<>();
4399 // jalview.bin.Console.errPrintln("Building ws menu again "
4400 // + Thread.currentThread());
4401 // TODO: add support for context dependent disabling of services based
4403 // alignment and current selection
4404 // TODO: add additional serviceHandle parameter to specify abstract
4406 // class independently of AbstractName
4407 // TODO: add in rediscovery GUI function to restart discoverer
4408 // TODO: group services by location as well as function and/or
4410 // object broker mechanism.
4411 final Vector<JMenu> wsmenu = new Vector<>();
4412 final IProgressIndicator af = me;
4415 * do not i18n these strings - they are hard-coded in class
4416 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4417 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4419 final JMenu msawsmenu = new JMenu("Alignment");
4420 final JMenu secstrmenu = new JMenu(
4421 "Secondary Structure Prediction");
4422 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4423 final JMenu analymenu = new JMenu("Analysis");
4424 final JMenu dismenu = new JMenu("Protein Disorder");
4425 // JAL-940 - only show secondary structure prediction services from
4426 // the legacy server
4427 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4429 Discoverer.services != null && (Discoverer.services.size() > 0))
4431 // TODO: refactor to allow list of AbstractName/Handler bindings to
4433 // stored or retrieved from elsewhere
4434 // No MSAWS used any more:
4435 // Vector msaws = null; // (Vector)
4436 // Discoverer.services.get("MsaWS");
4437 Vector<ServiceHandle> secstrpr = Discoverer.services
4439 if (secstrpr != null)
4441 // Add any secondary structure prediction services
4442 for (int i = 0, j = secstrpr.size(); i < j; i++)
4444 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4445 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4446 .getServiceClient(sh);
4447 int p = secstrmenu.getItemCount();
4448 impl.attachWSMenuEntry(secstrmenu, me);
4449 int q = secstrmenu.getItemCount();
4450 for (int litm = p; litm < q; litm++)
4452 legacyItems.add(secstrmenu.getItem(litm));
4458 // Add all submenus in the order they should appear on the web
4460 wsmenu.add(msawsmenu);
4461 wsmenu.add(secstrmenu);
4462 wsmenu.add(dismenu);
4463 wsmenu.add(analymenu);
4464 // No search services yet
4465 // wsmenu.add(seqsrchmenu);
4467 javax.swing.SwingUtilities.invokeLater(new Runnable()
4474 webService.removeAll();
4475 // first, add discovered services onto the webservices menu
4476 if (wsmenu.size() > 0)
4478 for (int i = 0, j = wsmenu.size(); i < j; i++)
4480 webService.add(wsmenu.get(i));
4485 webService.add(me.webServiceNoServices);
4487 // TODO: move into separate menu builder class.
4489 // logic for 2.11.1.4 is
4490 // always look to see if there is a discover. if there isn't
4491 // we can't show any Jws2 services
4492 // if there are services available, show them - regardless of
4493 // the 'show JWS2 preference'
4494 // if the discoverer is running then say so
4495 // otherwise offer to trigger discovery if 'show JWS2' is not
4497 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4498 if (jws2servs != null)
4500 if (jws2servs.hasServices())
4502 jws2servs.attachWSMenuEntry(webService, me);
4503 for (Jws2Instance sv : jws2servs.getServices())
4505 if (sv.description.toLowerCase(Locale.ROOT)
4508 for (JMenuItem jmi : legacyItems)
4510 jmi.setVisible(false);
4516 if (jws2servs.isRunning())
4518 JMenuItem tm = new JMenuItem(
4519 "Still discovering JABA Services");
4520 tm.setEnabled(false);
4523 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4525 JMenuItem enableJws2 = new JMenuItem(
4526 "Discover Web Services");
4527 enableJws2.setToolTipText(
4528 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4529 enableJws2.setEnabled(true);
4530 enableJws2.addActionListener(new ActionListener()
4534 public void actionPerformed(ActionEvent e)
4536 // start service discoverer, but ignore preference
4537 Desktop.instance.startServiceDiscovery(false,
4541 webService.add(enableJws2);
4545 build_urlServiceMenu(me.webService);
4546 build_fetchdbmenu(webService);
4547 for (JMenu item : wsmenu)
4549 if (item.getItemCount() == 0)
4551 item.setEnabled(false);
4555 item.setEnabled(true);
4558 } catch (Exception e)
4561 "Exception during web service menu building process.",
4566 } catch (Exception e)
4569 buildingMenu = false;
4576 * construct any groupURL type service menu entries.
4580 protected void build_urlServiceMenu(JMenu webService)
4582 // TODO: remove this code when 2.7 is released
4583 // DEBUG - alignmentView
4585 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4586 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4588 * @Override public void actionPerformed(ActionEvent e) {
4589 * jalview.datamodel.AlignmentView
4590 * .testSelectionViews(af.viewport.getAlignment(),
4591 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4593 * }); webService.add(testAlView);
4595 // TODO: refactor to RestClient discoverer and merge menu entries for
4596 // rest-style services with other types of analysis/calculation service
4597 // SHmmr test client - still being implemented.
4598 // DEBUG - alignmentView
4600 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4603 client.attachWSMenuEntry(
4604 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4610 * Searches the alignment sequences for xRefs and builds the Show
4611 * Cross-References menu (formerly called Show Products), with database
4612 * sources for which cross-references are found (protein sources for a
4613 * nucleotide alignment and vice versa)
4615 * @return true if Show Cross-references menu should be enabled
4617 public boolean canShowProducts()
4619 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4620 AlignmentI dataset = viewport.getAlignment().getDataset();
4622 showProducts.removeAll();
4623 final boolean dna = viewport.getAlignment().isNucleotide();
4625 if (seqs == null || seqs.length == 0)
4627 // nothing to see here.
4631 boolean showp = false;
4634 List<String> ptypes = new CrossRef(seqs, dataset)
4635 .findXrefSourcesForSequences(dna);
4637 for (final String source : ptypes)
4640 final AlignFrame af = this;
4641 JMenuItem xtype = new JMenuItem(source);
4642 xtype.addActionListener(new ActionListener()
4645 public void actionPerformed(ActionEvent e)
4647 showProductsFor(af.viewport.getSequenceSelection(), dna,
4651 showProducts.add(xtype);
4653 showProducts.setVisible(showp);
4654 showProducts.setEnabled(showp);
4655 } catch (Exception e)
4658 "canShowProducts threw an exception - please report to help@jalview.org",
4666 * Finds and displays cross-references for the selected sequences (protein
4667 * products for nucleotide sequences, dna coding sequences for peptides).
4670 * the sequences to show cross-references for
4672 * true if from a nucleotide alignment (so showing proteins)
4674 * the database to show cross-references for
4676 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4677 final String source)
4679 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4684 * Construct and display a new frame containing the translation of this
4685 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4688 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4690 AlignmentI al = null;
4693 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4695 al = dna.translateCdna(codeTable);
4696 } catch (Exception ex)
4698 Console.error("Exception during translation. Please report this !",
4700 final String msg = MessageManager.getString(
4701 "label.error_when_translating_sequences_submit_bug_report");
4702 final String errorTitle = MessageManager
4703 .getString("label.implementation_error")
4704 + MessageManager.getString("label.translation_failed");
4705 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4706 JvOptionPane.ERROR_MESSAGE);
4709 if (al == null || al.getHeight() == 0)
4711 final String msg = MessageManager.getString(
4712 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4713 final String errorTitle = MessageManager
4714 .getString("label.translation_failed");
4715 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4716 JvOptionPane.WARNING_MESSAGE);
4720 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4721 af.setFileFormat(this.currentFileFormat);
4722 final String newTitle = MessageManager
4723 .formatMessage("label.translation_of_params", new Object[]
4724 { this.getTitle(), codeTable.getId() });
4725 af.setTitle(newTitle);
4726 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4728 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4729 viewport.openSplitFrame(af, new Alignment(seqs));
4733 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4740 * Set the file format
4744 public void setFileFormat(FileFormatI format)
4746 this.currentFileFormat = format;
4750 * Try to load a features file onto the alignment.
4753 * contents or path to retrieve file or a File object
4755 * access mode of file (see jalview.io.AlignFile)
4756 * @return true if features file was parsed correctly.
4758 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4761 return avc.parseFeaturesFile(file, sourceType,
4762 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4767 public void refreshFeatureUI(boolean enableIfNecessary)
4769 // note - currently this is only still here rather than in the controller
4770 // because of the featureSettings hard reference that is yet to be
4772 if (enableIfNecessary)
4774 viewport.setShowSequenceFeatures(true);
4775 showSeqFeatures.setSelected(true);
4781 public void dragEnter(DropTargetDragEvent evt)
4786 public void dragExit(DropTargetEvent evt)
4791 public void dragOver(DropTargetDragEvent evt)
4796 public void dropActionChanged(DropTargetDragEvent evt)
4801 public void drop(DropTargetDropEvent evt)
4803 // JAL-1552 - acceptDrop required before getTransferable call for
4804 // Java's Transferable for native dnd
4805 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4806 Transferable t = evt.getTransferable();
4808 final AlignFrame thisaf = this;
4809 final List<Object> files = new ArrayList<>();
4810 List<DataSourceType> protocols = new ArrayList<>();
4814 Desktop.transferFromDropTarget(files, protocols, evt, t);
4815 } catch (Exception e)
4817 e.printStackTrace();
4821 new Thread(new Runnable()
4828 // check to see if any of these files have names matching sequences
4831 SequenceIdMatcher idm = new SequenceIdMatcher(
4832 viewport.getAlignment().getSequencesArray());
4834 * Object[] { String,SequenceI}
4836 ArrayList<Object[]> filesmatched = new ArrayList<>();
4837 ArrayList<Object[]> filesnotmatched = new ArrayList<>();
4838 for (int i = 0; i < files.size(); i++)
4841 Object file = files.get(i);
4842 String fileName = file.toString();
4844 DataSourceType protocol = (file instanceof File
4845 ? DataSourceType.FILE
4846 : FormatAdapter.checkProtocol(fileName));
4847 if (protocol == DataSourceType.FILE)
4850 if (file instanceof File)
4853 Platform.cacheFileData(fl);
4857 fl = new File(fileName);
4859 pdbfn = fl.getName();
4861 else if (protocol == DataSourceType.URL)
4863 URL url = new URL(fileName);
4864 pdbfn = url.getFile();
4866 if (pdbfn.length() > 0)
4868 // attempt to find a match in the alignment
4869 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4870 int l = 0, c = pdbfn.indexOf(".");
4871 while (mtch == null && c != -1)
4876 } while ((c = pdbfn.indexOf(".", l)) > l);
4879 pdbfn = pdbfn.substring(0, l);
4881 mtch = idm.findAllIdMatches(pdbfn);
4883 FileFormatI type = null;
4888 type = new IdentifyFile().identify(file, protocol);
4889 } catch (Exception ex)
4893 if (type != null && type.isStructureFile())
4895 filesmatched.add(new Object[] { file, protocol, mtch });
4899 // File wasn't named like one of the sequences or wasn't a PDB
4901 filesnotmatched.add(new Object[] { file, protocol, type });
4905 if (filesmatched.size() > 0)
4907 boolean autoAssociate = Cache
4908 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4911 String msg = MessageManager.formatMessage(
4912 "label.automatically_associate_structure_files_with_sequences_same_name",
4914 { Integer.valueOf(filesmatched.size())
4916 String ttl = MessageManager.getString(
4917 "label.automatically_associate_structure_files_by_name");
4918 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4919 ttl, JvOptionPane.YES_NO_OPTION);
4920 autoAssociate = choice == JvOptionPane.YES_OPTION;
4924 for (Object[] fm : filesmatched)
4926 // try and associate
4927 // TODO: may want to set a standard ID naming formalism for
4928 // associating PDB files which have no IDs.
4929 for (SequenceI toassoc : (SequenceI[]) fm[2])
4931 PDBEntry pe = new AssociatePdbFileWithSeq()
4932 .associatePdbWithSeq(fm[0].toString(),
4933 (DataSourceType) fm[1], toassoc, false,
4937 jalview.bin.Console.errPrintln("Associated file : "
4938 + (fm[0].toString()) + " with "
4939 + toassoc.getDisplayId(true));
4943 // TODO: do we need to update overview ? only if features are
4945 alignPanel.paintAlignment(true, false);
4951 * add declined structures as sequences
4953 for (Object[] o : filesmatched)
4955 filesnotmatched.add(new Object[] { o[0], o[1] });
4959 if (filesnotmatched.size() > 0)
4961 if (assocfiles > 0 && (Cache.getDefault(
4962 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4963 || JvOptionPane.showConfirmDialog(thisaf,
4964 "<html>" + MessageManager.formatMessage(
4965 "label.ignore_unmatched_dropped_files_info",
4968 filesnotmatched.size())
4971 MessageManager.getString(
4972 "label.ignore_unmatched_dropped_files"),
4973 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4977 for (Object[] fn : filesnotmatched)
4979 loadJalviewDataFile(fn[0], (DataSourceType) fn[1],
4980 (FileFormatI) fn[2], null);
4984 } catch (Exception ex)
4986 ex.printStackTrace();
4994 * Attempt to load a "dropped" file or URL string, by testing in turn for
4996 * <li>an Annotation file</li>
4997 * <li>a JNet file</li>
4998 * <li>a features file</li>
4999 * <li>else try to interpret as an alignment file</li>
5003 * either a filename or a URL string.
5005 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
5006 FileFormatI format, SequenceI assocSeq)
5008 // BH 2018 was String file
5011 if (sourceType == null)
5013 sourceType = FormatAdapter.checkProtocol(file);
5015 // if the file isn't identified, or not positively identified as some
5016 // other filetype (PFAM is default unidentified alignment file type) then
5017 // try to parse as annotation.
5018 boolean isAnnotation = (format == null
5019 || FileFormat.Pfam.equals(format))
5020 ? new AnnotationFile().annotateAlignmentView(viewport,
5026 // first see if its a T-COFFEE score file
5027 TCoffeeScoreFile tcf = null;
5030 tcf = new TCoffeeScoreFile(file, sourceType);
5033 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5037 new TCoffeeColourScheme(viewport.getAlignment()));
5038 isAnnotation = true;
5039 setStatus(MessageManager.getString(
5040 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5044 // some problem - if no warning its probable that the ID matching
5045 // process didn't work
5046 JvOptionPane.showMessageDialog(Desktop.desktop,
5047 tcf.getWarningMessage() == null
5048 ? MessageManager.getString(
5049 "label.check_file_matches_sequence_ids_alignment")
5050 : tcf.getWarningMessage(),
5051 MessageManager.getString(
5052 "label.problem_reading_tcoffee_score_file"),
5053 JvOptionPane.WARNING_MESSAGE);
5060 } catch (Exception x)
5063 "Exception when processing data source as T-COFFEE score file",
5069 // try to see if its a JNet 'concise' style annotation file *before*
5071 // try to parse it as a features file
5074 format = new IdentifyFile().identify(file, sourceType);
5076 if (FileFormat.FeatureSettings == format)
5078 if (featureSettings != null)
5080 featureSettings.load(file, sourceType);
5084 FeatureSettings.loadFeatureSettingsFile(getFeatureRenderer(),
5085 fileObject, sourceType);
5088 else if (FileFormat.ScoreMatrix == format)
5090 ScoreMatrixFile sm = new ScoreMatrixFile(
5091 new FileParse(file, sourceType));
5093 // todo: i18n this message
5094 setStatus(MessageManager.formatMessage(
5095 "label.successfully_loaded_matrix",
5096 sm.getMatrixName()));
5098 else if (FileFormat.Jnet.equals(format))
5100 JPredFile predictions = new JPredFile(file, sourceType);
5101 new JnetAnnotationMaker();
5102 JnetAnnotationMaker.add_annotation(predictions,
5103 viewport.getAlignment(), 0, false);
5104 viewport.getAlignment().setupJPredAlignment();
5105 isAnnotation = true;
5107 // else if (IdentifyFile.FeaturesFile.equals(format))
5108 else if (FileFormat.Features.equals(format))
5110 if (parseFeaturesFile(file, sourceType))
5112 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5113 if (splitFrame != null)
5115 splitFrame.repaint();
5119 alignPanel.paintAlignment(true, true);
5125 new FileLoader().LoadFile(viewport, file, sourceType, format);
5132 alignPanel.adjustAnnotationHeight();
5133 viewport.updateSequenceIdColours();
5134 buildSortByAnnotationScoresMenu();
5135 alignPanel.paintAlignment(true, true);
5137 } catch (Exception ex)
5139 ex.printStackTrace();
5140 } catch (OutOfMemoryError oom)
5145 } catch (Exception x)
5150 + (sourceType != null
5151 ? (sourceType == DataSourceType.PASTE
5153 : "using " + sourceType + " from "
5157 ? "(parsing as '" + format + "' file)"
5159 oom, Desktop.desktop);
5164 * Method invoked by the ChangeListener on the tabbed pane, in other words
5165 * when a different tabbed pane is selected by the user or programmatically.
5168 public void tabSelectionChanged(int index)
5173 * update current Overview window title (if there is one)
5174 * to add view name "Original" if necessary
5176 alignPanel.setOverviewTitle(this);
5179 * switch panels and set Overview title (if there is one
5180 * because it was opened automatically)
5182 alignPanel = alignPanels.get(index);
5183 alignPanel.setOverviewTitle(this);
5185 viewport = alignPanel.av;
5186 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5187 setMenusFromViewport(viewport);
5188 if (featureSettings != null && featureSettings.isOpen()
5189 && featureSettings.fr.getViewport() != viewport)
5191 if (viewport.isShowSequenceFeatures())
5193 // refresh the featureSettings to reflect UI change
5194 showFeatureSettingsUI();
5198 // close feature settings for this view.
5199 featureSettings.close();
5206 * 'focus' any colour slider that is open to the selected viewport
5208 if (viewport.getConservationSelected())
5210 SliderPanel.setConservationSlider(alignPanel,
5211 viewport.getResidueShading(), alignPanel.getViewName());
5215 SliderPanel.hideConservationSlider();
5217 if (viewport.getAbovePIDThreshold())
5219 SliderPanel.setPIDSliderSource(alignPanel,
5220 viewport.getResidueShading(), alignPanel.getViewName());
5224 SliderPanel.hidePIDSlider();
5228 * If there is a frame linked to this one in a SplitPane, switch it to the
5229 * same view tab index. No infinite recursion of calls should happen, since
5230 * tabSelectionChanged() should not get invoked on setting the selected
5231 * index to an unchanged value. Guard against setting an invalid index
5232 * before the new view peer tab has been created.
5234 final AlignViewportI peer = viewport.getCodingComplement();
5237 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5238 .getAlignPanel().alignFrame;
5239 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5241 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5247 * On right mouse click on view tab, prompt for and set new view name.
5250 public void tabbedPane_mousePressed(MouseEvent e)
5252 if (e.isPopupTrigger())
5254 String msg = MessageManager.getString("label.enter_view_name");
5255 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5256 String reply = JvOptionPane.showInputDialog(msg, ttl);
5260 viewport.setViewName(reply);
5261 // TODO warn if reply is in getExistingViewNames()?
5262 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5267 public AlignViewport getCurrentView()
5273 * Open the dialog for regex description parsing.
5276 protected void extractScores_actionPerformed(ActionEvent e)
5278 ParseProperties pp = new jalview.analysis.ParseProperties(
5279 viewport.getAlignment());
5280 // TODO: verify regex and introduce GUI dialog for version 2.5
5281 // if (pp.getScoresFromDescription("col", "score column ",
5282 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5284 if (pp.getScoresFromDescription("description column",
5285 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5287 buildSortByAnnotationScoresMenu();
5295 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5299 protected void showDbRefs_actionPerformed(ActionEvent e)
5301 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5307 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5311 protected void showNpFeats_actionPerformed(ActionEvent e)
5313 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5317 * find the viewport amongst the tabs in this alignment frame and close that
5322 public boolean closeView(AlignViewportI av)
5326 this.closeMenuItem_actionPerformed(false);
5329 Component[] comp = tabbedPane.getComponents();
5330 for (int i = 0; comp != null && i < comp.length; i++)
5332 if (comp[i] instanceof AlignmentPanel)
5334 if (((AlignmentPanel) comp[i]).av == av)
5337 closeView((AlignmentPanel) comp[i]);
5345 protected void build_fetchdbmenu(JMenu webService)
5347 // Temporary hack - DBRef Fetcher always top level ws entry.
5348 // TODO We probably want to store a sequence database checklist in
5349 // preferences and have checkboxes.. rather than individual sources selected
5351 final JMenu rfetch = new JMenu(
5352 MessageManager.getString("action.fetch_db_references"));
5353 rfetch.setToolTipText(MessageManager.getString(
5354 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5355 webService.add(rfetch);
5357 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5358 MessageManager.getString("option.trim_retrieved_seqs"));
5359 trimrs.setToolTipText(
5360 MessageManager.getString("label.trim_retrieved_sequences"));
5362 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5363 trimrs.addActionListener(new ActionListener()
5366 public void actionPerformed(ActionEvent e)
5368 trimrs.setSelected(trimrs.isSelected());
5369 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5370 Boolean.valueOf(trimrs.isSelected()).toString());
5374 JMenuItem fetchr = new JMenuItem(
5375 MessageManager.getString("label.standard_databases"));
5376 fetchr.setToolTipText(
5377 MessageManager.getString("label.fetch_embl_uniprot"));
5378 fetchr.addActionListener(new ActionListener()
5382 public void actionPerformed(ActionEvent e)
5384 new Thread(new Runnable()
5389 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5390 .getAlignment().isNucleotide();
5391 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5392 alignPanel.av.getSequenceSelection(),
5393 alignPanel.alignFrame, null,
5394 alignPanel.alignFrame.featureSettings, isNucleotide);
5395 dbRefFetcher.addListener(new FetchFinishedListenerI()
5398 public void finished()
5401 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5402 .getFeatureSettingsModels())
5405 alignPanel.av.mergeFeaturesStyle(srcSettings);
5407 AlignFrame.this.setMenusForViewport();
5410 dbRefFetcher.fetchDBRefs(false);
5418 new Thread(new Runnable()
5423 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5424 .getSequenceFetcherSingleton();
5425 javax.swing.SwingUtilities.invokeLater(new Runnable()
5430 String[] dbclasses = sf.getNonAlignmentSources();
5431 List<DbSourceProxy> otherdb;
5432 JMenu dfetch = new JMenu();
5433 JMenu ifetch = new JMenu();
5434 JMenuItem fetchr = null;
5435 int comp = 0, icomp = 0, mcomp = 15;
5436 String mname = null;
5438 for (String dbclass : dbclasses)
5440 otherdb = sf.getSourceProxy(dbclass);
5441 // add a single entry for this class, or submenu allowing 'fetch
5443 if (otherdb == null || otherdb.size() < 1)
5449 mname = "From " + dbclass;
5451 if (otherdb.size() == 1)
5453 final DbSourceProxy[] dassource = otherdb
5454 .toArray(new DbSourceProxy[0]);
5455 DbSourceProxy src = otherdb.get(0);
5456 fetchr = new JMenuItem(src.getDbSource());
5457 fetchr.addActionListener(new ActionListener()
5461 public void actionPerformed(ActionEvent e)
5463 new Thread(new Runnable()
5469 boolean isNucleotide = alignPanel.alignFrame
5470 .getViewport().getAlignment()
5472 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5473 alignPanel.av.getSequenceSelection(),
5474 alignPanel.alignFrame, dassource,
5475 alignPanel.alignFrame.featureSettings,
5478 .addListener(new FetchFinishedListenerI()
5481 public void finished()
5483 FeatureSettingsModelI srcSettings = dassource[0]
5484 .getFeatureColourScheme();
5485 alignPanel.av.mergeFeaturesStyle(
5487 AlignFrame.this.setMenusForViewport();
5490 dbRefFetcher.fetchDBRefs(false);
5496 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5497 MessageManager.formatMessage(
5498 "label.fetch_retrieve_from", new Object[]
5499 { src.getDbName() })));
5505 final DbSourceProxy[] dassource = otherdb
5506 .toArray(new DbSourceProxy[0]);
5508 DbSourceProxy src = otherdb.get(0);
5509 fetchr = new JMenuItem(MessageManager
5510 .formatMessage("label.fetch_all_param", new Object[]
5511 { src.getDbSource() }));
5512 fetchr.addActionListener(new ActionListener()
5515 public void actionPerformed(ActionEvent e)
5517 new Thread(new Runnable()
5523 boolean isNucleotide = alignPanel.alignFrame
5524 .getViewport().getAlignment()
5526 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5527 alignPanel.av.getSequenceSelection(),
5528 alignPanel.alignFrame, dassource,
5529 alignPanel.alignFrame.featureSettings,
5532 .addListener(new FetchFinishedListenerI()
5535 public void finished()
5537 AlignFrame.this.setMenusForViewport();
5540 dbRefFetcher.fetchDBRefs(false);
5546 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5547 MessageManager.formatMessage(
5548 "label.fetch_retrieve_from_all_sources",
5550 { Integer.valueOf(otherdb.size())
5552 src.getDbSource(), src.getDbName() })));
5555 // and then build the rest of the individual menus
5556 ifetch = new JMenu(MessageManager.formatMessage(
5557 "label.source_from_db_source", new Object[]
5558 { src.getDbSource() }));
5560 String imname = null;
5562 for (DbSourceProxy sproxy : otherdb)
5564 String dbname = sproxy.getDbName();
5565 String sname = dbname.length() > 5
5566 ? dbname.substring(0, 5) + "..."
5568 String msname = dbname.length() > 10
5569 ? dbname.substring(0, 10) + "..."
5573 imname = MessageManager
5574 .formatMessage("label.from_msname", new Object[]
5577 fetchr = new JMenuItem(msname);
5578 final DbSourceProxy[] dassrc = { sproxy };
5579 fetchr.addActionListener(new ActionListener()
5583 public void actionPerformed(ActionEvent e)
5585 new Thread(new Runnable()
5591 boolean isNucleotide = alignPanel.alignFrame
5592 .getViewport().getAlignment()
5594 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5595 alignPanel.av.getSequenceSelection(),
5596 alignPanel.alignFrame, dassrc,
5597 alignPanel.alignFrame.featureSettings,
5600 .addListener(new FetchFinishedListenerI()
5603 public void finished()
5605 AlignFrame.this.setMenusForViewport();
5608 dbRefFetcher.fetchDBRefs(false);
5614 fetchr.setToolTipText(
5615 "<html>" + MessageManager.formatMessage(
5616 "label.fetch_retrieve_from", new Object[]
5620 if (++icomp >= mcomp || i == (otherdb.size()))
5622 ifetch.setText(MessageManager.formatMessage(
5623 "label.source_to_target", imname, sname));
5625 ifetch = new JMenu();
5633 if (comp >= mcomp || dbi >= (dbclasses.length))
5635 dfetch.setText(MessageManager.formatMessage(
5636 "label.source_to_target", mname, dbclass));
5638 dfetch = new JMenu();
5651 * Left justify the whole alignment.
5654 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5656 avc.justify_Region(true);
5660 * Right justify the whole alignment.
5663 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5665 avc.justify_Region(false);
5669 public void setShowSeqFeatures(boolean b)
5671 showSeqFeatures.setSelected(b);
5672 viewport.setShowSequenceFeatures(b);
5679 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5680 * awt.event.ActionEvent)
5683 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5685 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5686 alignPanel.paintAlignment(false, false);
5690 protected void updateShowSSRadioButtons(JMenu showSS, ButtonGroup ssButtonGroup){
5692 List<String> ssSources = new ArrayList<String>();
5693 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5694 .getAlignmentAnnotation();
5696 ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(anns);
5698 // Get the currently selected radio button
5699 String selectedButtonModelName = getSelectedRadioButtonDisplayString(ssButtonGroup);
5700 boolean selectedButtonModel = false;
5702 // Clear existing radio buttons
5704 JRadioButtonMenuItem radioButtonAllSS = new JRadioButtonMenuItem("All");
5705 radioButtonAllSS.addActionListener(new ActionListener() {
5707 public void actionPerformed(ActionEvent e) {
5708 showSS_actionPerformed("All");
5711 ssButtonGroup.add(radioButtonAllSS);
5712 showSS.add(radioButtonAllSS);
5714 JRadioButtonMenuItem radioButtonNoneSS = new JRadioButtonMenuItem("None");
5715 radioButtonNoneSS.addActionListener(new ActionListener() {
5717 public void actionPerformed(ActionEvent e) {
5718 showSS_actionPerformed("None");
5721 ssButtonGroup.add(radioButtonNoneSS);
5722 showSS.add(radioButtonNoneSS);
5723 showSS.addSeparator();
5725 for(String ssSource : ssSources) {
5727 JRadioButtonMenuItem radioButton = new JRadioButtonMenuItem(ssSource);
5728 radioButton.addActionListener(new ActionListener() {
5730 public void actionPerformed(ActionEvent e) {
5731 showSS_actionPerformed(ssSource);
5734 ssButtonGroup.add(radioButton);
5735 showSS.add(radioButton);
5737 // Check if this radio button's name matches the selected radio button's name
5738 if (ssSource.equals(selectedButtonModelName)) {
5739 radioButton.setSelected(true); // Select this radio button
5740 selectedButtonModel = true;
5745 if (selectedButtonModelName == "None") {
5746 // If no radio button was previously selected, select "All"
5747 ssButtonGroup.setSelected(radioButtonNoneSS.getModel(), true);
5748 selectedButtonModel = true;
5750 if (!selectedButtonModel) {
5751 // If no radio button was previously selected, select "All"
5752 ssButtonGroup.setSelected(radioButtonAllSS.getModel(), true);
5757 protected void showSS_actionPerformed(String ssSourceSelection){
5760 AlignmentAnnotation[] annotations = alignPanel.getAlignment()
5761 .getAlignmentAnnotation();
5763 for (AlignmentAnnotation aa: annotations) {
5765 for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
5767 if (label.equals(aa.label)) {
5771 if(ssSourceSelection == "All") {
5776 String ssSource = AlignmentUtils.extractSSSourceFromAnnotationDescription(aa);
5777 if(ssSource.equals(ssSourceSelection)) {
5789 List<AlignCalcWorkerI> workers = viewport.getCalcManager()
5790 .getRegisteredWorkersOfClass(SecondaryStructureConsensusThread.class);
5791 if (!workers.isEmpty()) {
5793 viewport.getCalcManager().startWorker(workers.remove(0));
5797 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5798 alignPanel.updateAnnotation();
5799 alignPanel.paintAlignment(true, true);
5805 protected String getSelectedRadioButtonDisplayString(ButtonGroup ssButtonGroup) {
5806 Enumeration<AbstractButton> buttons = ssButtonGroup.getElements();
5807 while (buttons.hasMoreElements()) {
5808 AbstractButton button = buttons.nextElement();
5809 if (button.isSelected()) {
5810 return button.getText();
5813 return null; // No radio button is selected
5820 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5824 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5826 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5827 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5835 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5836 * .event.ActionEvent)
5839 protected void showGroupConservation_actionPerformed(ActionEvent e)
5841 viewport.setShowGroupConservation(showGroupConservation.getState());
5842 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5849 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5850 * .event.ActionEvent)
5853 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5855 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5856 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5860 protected void showSSConsensusHistogram_actionPerformed(ActionEvent e)
5862 viewport.setShowSSConsensusHistogram(showSSConsensusHistogram.getState());
5863 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5870 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5871 * .event.ActionEvent)
5874 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5876 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5877 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5881 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5883 showSequenceLogo.setState(true);
5884 viewport.setShowSequenceLogo(true);
5885 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5886 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5890 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5892 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5899 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5900 * .event.ActionEvent)
5903 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5905 if (avc.makeGroupsFromSelection())
5907 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5908 alignPanel.updateAnnotation();
5909 alignPanel.paintAlignment(true,
5910 viewport.needToUpdateStructureViews());
5914 public void clearAlignmentSeqRep()
5916 // TODO refactor alignmentseqrep to controller
5917 if (viewport.getAlignment().hasSeqrep())
5919 viewport.getAlignment().setSeqrep(null);
5920 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5921 alignPanel.updateAnnotation();
5922 alignPanel.paintAlignment(true, true);
5927 protected void createGroup_actionPerformed(ActionEvent e)
5929 if (avc.createGroup())
5931 if (applyAutoAnnotationSettings.isSelected())
5933 alignPanel.updateAnnotation(true, false);
5935 alignPanel.alignmentChanged();
5940 protected void unGroup_actionPerformed(ActionEvent e)
5944 alignPanel.alignmentChanged();
5949 * make the given alignmentPanel the currently selected tab
5951 * @param alignmentPanel
5953 public void setDisplayedView(AlignmentPanel alignmentPanel)
5955 if (!viewport.getSequenceSetId()
5956 .equals(alignmentPanel.av.getSequenceSetId()))
5958 throw new Error(MessageManager.getString(
5959 "error.implementation_error_cannot_show_view_alignment_frame"));
5961 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5962 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5964 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5969 * Action on selection of menu options to Show or Hide annotations.
5972 * @param forSequences
5973 * update sequence-related annotations
5974 * @param forAlignment
5975 * update non-sequence-related annotations
5978 public void setAnnotationsVisibility(boolean visible,
5979 boolean forSequences, boolean forAlignment)
5981 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5982 .getAlignmentAnnotation();
5987 for (AlignmentAnnotation aa : anns)
5990 * don't display non-positional annotations on an alignment
5992 if (aa.annotations == null)
5996 boolean apply = (aa.sequenceRef == null && forAlignment)
5997 || (aa.sequenceRef != null && forSequences);
6000 aa.visible = visible;
6003 alignPanel.validateAnnotationDimensions(true);
6004 // TODO this triggers relayout of annotation panel - otherwise annotation
6005 // label height is different to panel height
6006 alignPanel.fontChanged();
6007 alignPanel.alignmentChanged();
6011 * Store selected annotation sort order for the view and repaint.
6014 protected void sortAnnotations_actionPerformed()
6016 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
6018 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
6019 alignPanel.paintAlignment(false, false);
6024 * @return alignment panels in this alignment frame
6026 public List<? extends AlignmentViewPanel> getAlignPanels()
6028 // alignPanels is never null
6029 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
6034 * Open a new alignment window, with the cDNA associated with this (protein)
6035 * alignment, aligned as is the protein.
6037 protected void viewAsCdna_actionPerformed()
6039 // TODO no longer a menu action - refactor as required
6040 final AlignmentI alignment = getViewport().getAlignment();
6041 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
6042 if (mappings == null)
6046 List<SequenceI> cdnaSeqs = new ArrayList<>();
6047 for (SequenceI aaSeq : alignment.getSequences())
6049 for (AlignedCodonFrame acf : mappings)
6051 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
6055 * There is a cDNA mapping for this protein sequence - add to new
6056 * alignment. It will share the same dataset sequence as other mapped
6057 * cDNA (no new mappings need to be created).
6059 final Sequence newSeq = new Sequence(dnaSeq);
6060 newSeq.setDatasetSequence(dnaSeq);
6061 cdnaSeqs.add(newSeq);
6065 if (cdnaSeqs.size() == 0)
6067 // show a warning dialog no mapped cDNA
6070 AlignmentI cdna = new Alignment(
6071 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
6072 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
6073 AlignFrame.DEFAULT_HEIGHT);
6074 cdna.alignAs(alignment);
6075 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
6077 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
6078 AlignFrame.DEFAULT_HEIGHT);
6082 * Set visibility of dna/protein complement view (available when shown in a
6088 protected void showComplement_actionPerformed(boolean show)
6090 SplitContainerI sf = getSplitViewContainer();
6093 sf.setComplementVisible(this, show);
6098 * Generate the reverse (optionally complemented) of the selected sequences,
6099 * and add them to the alignment
6102 protected void showReverse_actionPerformed(boolean complement)
6104 AlignmentI al = null;
6107 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
6108 al = dna.reverseCdna(complement);
6109 viewport.addAlignment(al, "");
6110 addHistoryItem(new EditCommand(
6111 MessageManager.getString("label.add_sequences"), Action.PASTE,
6112 al.getSequencesArray(), 0, al.getWidth(),
6113 viewport.getAlignment()));
6114 } catch (Exception ex)
6116 jalview.bin.Console.errPrintln(ex.getMessage());
6122 * Try to run a script in the Groovy console, having first ensured that this
6123 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
6124 * be targeted at this alignment.
6127 protected void runGroovy_actionPerformed()
6129 Jalview.getInstance().setCurrentAlignFrame(this);
6130 groovy.console.ui.Console console = Desktop.getGroovyConsole();
6131 if (console != null)
6135 console.setVariable(JalviewObjectI.currentAlFrameName, this);
6136 console.runScript();
6137 } catch (Exception ex)
6139 jalview.bin.Console.errPrintln((ex.toString()));
6140 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
6141 MessageManager.getString("label.couldnt_run_groovy_script"),
6142 MessageManager.getString("label.groovy_support_failed"),
6143 JvOptionPane.ERROR_MESSAGE);
6149 .errPrintln("Can't run Groovy script as console not found");
6154 * Hides columns containing (or not containing) a specified feature, provided
6155 * that would not leave all columns hidden
6157 * @param featureType
6158 * @param columnsContaining
6161 public boolean hideFeatureColumns(String featureType,
6162 boolean columnsContaining)
6164 boolean notForHiding = avc.markColumnsContainingFeatures(
6165 columnsContaining, false, false, featureType);
6168 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6169 false, featureType))
6171 getViewport().hideSelectedColumns();
6179 protected void selectHighlightedColumns_actionPerformed(
6180 ActionEvent actionEvent)
6182 // include key modifier check in case user selects from menu
6183 avc.markHighlightedColumns(
6184 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6185 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6186 | ActionEvent.CTRL_MASK)) != 0);
6190 protected void copyHighlightedColumns_actionPerformed(
6191 ActionEvent actionEvent)
6193 avc.copyHighlightedRegionsToClipboard();
6197 * Rebuilds the Colour menu, including any user-defined colours which have
6198 * been loaded either on startup or during the session
6200 public void buildColourMenu()
6202 colourMenu.removeAll();
6204 colourMenu.add(applyToAllGroups);
6205 colourMenu.add(textColour);
6206 colourMenu.addSeparator();
6208 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6209 viewport.getAlignment(), false);
6211 colourMenu.add(annotationColour);
6212 bg.add(annotationColour);
6213 colourMenu.addSeparator();
6214 colourMenu.add(conservationMenuItem);
6215 colourMenu.add(modifyConservation);
6216 colourMenu.add(abovePIDThreshold);
6217 colourMenu.add(modifyPID);
6219 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6220 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6224 * Open a dialog (if not already open) that allows the user to select and
6225 * calculate PCA or Tree analysis
6227 protected void openTreePcaDialog()
6229 if (alignPanel.getCalculationDialog() == null)
6231 new CalculationChooser(AlignFrame.this);
6236 protected void loadVcf_actionPerformed()
6238 JalviewFileChooser chooser = new JalviewFileChooser(
6239 Cache.getProperty("LAST_DIRECTORY"));
6240 chooser.setFileView(new JalviewFileView());
6241 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6242 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6243 final AlignFrame us = this;
6244 chooser.setResponseHandler(0, () -> {
6245 String choice = chooser.getSelectedFile().getPath();
6246 Cache.setProperty("LAST_DIRECTORY", choice);
6247 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6248 new VCFLoader(choice).loadVCF(seqs, us);
6250 chooser.showOpenDialog(null);
6254 private Rectangle lastFeatureSettingsBounds = null;
6257 public void setFeatureSettingsGeometry(Rectangle bounds)
6259 lastFeatureSettingsBounds = bounds;
6263 public Rectangle getFeatureSettingsGeometry()
6265 return lastFeatureSettingsBounds;
6270 class PrintThread extends Thread
6274 public PrintThread(AlignmentPanel ap)
6279 static PageFormat pf;
6284 PrinterJob printJob = PrinterJob.getPrinterJob();
6288 printJob.setPrintable(ap, pf);
6292 printJob.setPrintable(ap);
6295 if (printJob.printDialog())
6300 } catch (Exception PrintException)
6302 PrintException.printStackTrace();