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 new Thread(new Runnable() {
3869 JInternalFrame frame = new JInternalFrame();
3870 frame.setFrameIcon(null);
3871 frame.setContentPane(new PairwiseAlignPanel(viewport));
3872 Desktop.addInternalFrame(frame,
3873 MessageManager.getString("action.pairwise_alignment"), 600,
3882 public void autoCalculate_actionPerformed(ActionEvent e)
3884 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3885 if (viewport.autoCalculateConsensus)
3887 viewport.firePropertyChange("alignment", null,
3888 viewport.getAlignment().getSequences());
3893 public void sortByTreeOption_actionPerformed(ActionEvent e)
3895 viewport.sortByTree = sortByTree.isSelected();
3899 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3901 viewport.followSelection = listenToViewSelections.isSelected();
3905 * Constructs a tree panel and adds it to the desktop
3908 * tree type (NJ or AV)
3910 * name of score model used to compute the tree
3912 * parameters for the distance or similarity calculation
3914 void newTreePanel(String type, String modelName,
3915 SimilarityParamsI options)
3917 String frameTitle = "";
3920 boolean onSelection = false;
3921 if (viewport.getSelectionGroup() != null
3922 && viewport.getSelectionGroup().getSize() > 0)
3924 SequenceGroup sg = viewport.getSelectionGroup();
3926 /* Decide if the selection is a column region */
3927 for (SequenceI _s : sg.getSequences())
3929 if (_s.getLength() < sg.getEndRes())
3931 JvOptionPane.showMessageDialog(Desktop.desktop,
3932 MessageManager.getString(
3933 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3934 MessageManager.getString(
3935 "label.sequences_selection_not_aligned"),
3936 JvOptionPane.WARNING_MESSAGE);
3945 if (viewport.getAlignment().getHeight() < 2)
3951 tp = new TreePanel(alignPanel, type, modelName, options);
3952 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3954 frameTitle += " from ";
3956 if (viewport.getViewName() != null)
3958 frameTitle += viewport.getViewName() + " of ";
3961 frameTitle += this.title;
3963 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3974 public void addSortByOrderMenuItem(String title,
3975 final AlignmentOrder order)
3977 final JMenuItem item = new JMenuItem(MessageManager
3978 .formatMessage("action.by_title_param", new Object[]
3981 item.addActionListener(new java.awt.event.ActionListener()
3984 public void actionPerformed(ActionEvent e)
3986 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3988 // TODO: JBPNote - have to map order entries to curent SequenceI
3990 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3992 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3993 viewport.getAlignment()));
3995 alignPanel.paintAlignment(true, false);
4001 * Add a new sort by annotation score menu item
4004 * the menu to add the option to
4006 * the label used to retrieve scores for each sequence on the
4009 public void addSortByAnnotScoreMenuItem(JMenu sort,
4010 final String scoreLabel)
4012 final JMenuItem item = new JMenuItem(scoreLabel);
4014 item.addActionListener(new java.awt.event.ActionListener()
4017 public void actionPerformed(ActionEvent e)
4019 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4020 AlignmentSorter.sortByAnnotationScore(scoreLabel,
4021 viewport.getAlignment());// ,viewport.getSelectionGroup());
4022 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
4023 viewport.getAlignment()));
4024 alignPanel.paintAlignment(true, false);
4030 * last hash for alignment's annotation array - used to minimise cost of
4033 protected int _annotationScoreVectorHash;
4036 * search the alignment and rebuild the sort by annotation score submenu the
4037 * last alignment annotation vector hash is stored to minimize cost of
4038 * rebuilding in subsequence calls.
4042 public void buildSortByAnnotationScoresMenu()
4044 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4049 if (viewport.getAlignment().getAlignmentAnnotation()
4050 .hashCode() != _annotationScoreVectorHash)
4052 sortByAnnotScore.removeAll();
4053 // almost certainly a quicker way to do this - but we keep it simple
4054 Hashtable<String, String> scoreSorts = new Hashtable<>();
4055 AlignmentAnnotation aann[];
4056 for (SequenceI sqa : viewport.getAlignment().getSequences())
4058 aann = sqa.getAnnotation();
4059 for (int i = 0; aann != null && i < aann.length; i++)
4061 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4063 scoreSorts.put(aann[i].label, aann[i].label);
4067 Enumeration<String> labels = scoreSorts.keys();
4068 while (labels.hasMoreElements())
4070 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4072 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4075 _annotationScoreVectorHash = viewport.getAlignment()
4076 .getAlignmentAnnotation().hashCode();
4081 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4082 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4083 * call. Listeners are added to remove the menu item when the treePanel is
4084 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4088 public void buildTreeSortMenu()
4090 sortByTreeMenu.removeAll();
4092 List<Component> comps = PaintRefresher.components
4093 .get(viewport.getSequenceSetId());
4094 List<TreePanel> treePanels = new ArrayList<>();
4095 for (Component comp : comps)
4097 if (comp instanceof TreePanel)
4099 treePanels.add((TreePanel) comp);
4103 if (treePanels.size() < 1)
4105 sortByTreeMenu.setVisible(false);
4109 sortByTreeMenu.setVisible(true);
4111 for (final TreePanel tp : treePanels)
4113 final JMenuItem item = new JMenuItem(tp.getTitle());
4114 item.addActionListener(new java.awt.event.ActionListener()
4117 public void actionPerformed(ActionEvent e)
4119 tp.sortByTree_actionPerformed();
4120 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4125 sortByTreeMenu.add(item);
4129 public boolean sortBy(AlignmentOrder alorder, String undoname)
4131 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4132 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4133 if (undoname != null)
4135 addHistoryItem(new OrderCommand(undoname, oldOrder,
4136 viewport.getAlignment()));
4138 alignPanel.paintAlignment(true, false);
4143 * Work out whether the whole set of sequences or just the selected set will
4144 * be submitted for multiple alignment.
4147 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4149 // Now, check we have enough sequences
4150 AlignmentView msa = null;
4152 if ((viewport.getSelectionGroup() != null)
4153 && (viewport.getSelectionGroup().getSize() > 1))
4155 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4156 // some common interface!
4158 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4159 * SequenceI[sz = seqs.getSize(false)];
4161 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4162 * seqs.getSequenceAt(i); }
4164 msa = viewport.getAlignmentView(true);
4166 else if (viewport.getSelectionGroup() != null
4167 && viewport.getSelectionGroup().getSize() == 1)
4169 int option = JvOptionPane.showConfirmDialog(this,
4170 MessageManager.getString("warn.oneseq_msainput_selection"),
4171 MessageManager.getString("label.invalid_selection"),
4172 JvOptionPane.OK_CANCEL_OPTION);
4173 if (option == JvOptionPane.OK_OPTION)
4175 msa = viewport.getAlignmentView(false);
4180 msa = viewport.getAlignmentView(false);
4186 * Decides what is submitted to a secondary structure prediction service: the
4187 * first sequence in the alignment, or in the current selection, or, if the
4188 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4189 * region or the whole alignment. (where the first sequence in the set is the
4190 * one that the prediction will be for).
4192 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4194 AlignmentView seqs = null;
4196 if ((viewport.getSelectionGroup() != null)
4197 && (viewport.getSelectionGroup().getSize() > 0))
4199 seqs = viewport.getAlignmentView(true);
4203 seqs = viewport.getAlignmentView(false);
4205 // limit sequences - JBPNote in future - could spawn multiple prediction
4207 // TODO: viewport.getAlignment().isAligned is a global state - the local
4208 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4209 if (!viewport.getAlignment().isAligned(false))
4211 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4212 // TODO: if seqs.getSequences().length>1 then should really have warned
4226 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4228 // Pick the tree file
4229 JalviewFileChooser chooser = new JalviewFileChooser(
4230 Cache.getProperty("LAST_DIRECTORY"));
4231 chooser.setFileView(new JalviewFileView());
4232 chooser.setDialogTitle(
4233 MessageManager.getString("label.select_newick_like_tree_file"));
4234 chooser.setToolTipText(
4235 MessageManager.getString("label.load_tree_file"));
4237 chooser.setResponseHandler(0, () -> {
4238 String filePath = chooser.getSelectedFile().getPath();
4239 Cache.setProperty("LAST_DIRECTORY", filePath);
4240 NewickFile fin = null;
4243 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4244 DataSourceType.FILE));
4245 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4246 } catch (Exception ex)
4248 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4249 MessageManager.getString("label.problem_reading_tree_file"),
4250 JvOptionPane.WARNING_MESSAGE);
4251 ex.printStackTrace();
4253 if (fin != null && fin.hasWarningMessage())
4255 JvOptionPane.showMessageDialog(Desktop.desktop,
4256 fin.getWarningMessage(),
4258 .getString("label.possible_problem_with_tree_file"),
4259 JvOptionPane.WARNING_MESSAGE);
4262 chooser.showOpenDialog(this);
4265 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4267 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4270 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4271 int h, int x, int y)
4273 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4277 * Add a treeviewer for the tree extracted from a Newick file object to the
4278 * current alignment view
4285 * Associated alignment input data (or null)
4294 * @return TreePanel handle
4296 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4297 AlignmentView input, int w, int h, int x, int y)
4299 TreePanel tp = null;
4305 if (nf.getTree() != null)
4307 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4313 tp.setLocation(x, y);
4316 Desktop.addInternalFrame(tp, treeTitle, w, h);
4318 } catch (Exception ex)
4320 ex.printStackTrace();
4326 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4329 int w = 400, h = 500;
4333 NewickFile fin = new NewickFile(
4334 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4335 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4336 + (aa.sequenceRef != null
4337 ? (" for " + aa.sequenceRef.getDisplayId(false))
4340 showColumnWiseTree(fin, aa, title, w, h, x, y);
4341 } catch (Throwable xx)
4343 Console.error("Unexpected exception showing tree for contact matrix",
4348 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4349 String treeTitle, int w, int h, int x, int y)
4354 if (nf.getTree() == null)
4358 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4364 tp.setLocation(x, y);
4367 Desktop.addInternalFrame(tp, treeTitle, w, h);
4369 } catch (Throwable xx)
4371 Console.error("Unexpected exception showing tree for contact matrix",
4377 private boolean buildingMenu = false;
4380 * Generates menu items and listener event actions for web service clients
4383 public void BuildWebServiceMenu()
4385 while (buildingMenu)
4390 .errPrintln("Waiting for building menu to finish.");
4392 } catch (Exception e)
4396 final AlignFrame me = this;
4397 buildingMenu = true;
4398 new Thread(new Runnable()
4403 final List<JMenuItem> legacyItems = new ArrayList<>();
4406 // jalview.bin.Console.errPrintln("Building ws menu again "
4407 // + Thread.currentThread());
4408 // TODO: add support for context dependent disabling of services based
4410 // alignment and current selection
4411 // TODO: add additional serviceHandle parameter to specify abstract
4413 // class independently of AbstractName
4414 // TODO: add in rediscovery GUI function to restart discoverer
4415 // TODO: group services by location as well as function and/or
4417 // object broker mechanism.
4418 final Vector<JMenu> wsmenu = new Vector<>();
4419 final IProgressIndicator af = me;
4422 * do not i18n these strings - they are hard-coded in class
4423 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4424 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4426 final JMenu msawsmenu = new JMenu("Alignment");
4427 final JMenu secstrmenu = new JMenu(
4428 "Secondary Structure Prediction");
4429 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4430 final JMenu analymenu = new JMenu("Analysis");
4431 final JMenu dismenu = new JMenu("Protein Disorder");
4432 // JAL-940 - only show secondary structure prediction services from
4433 // the legacy server
4434 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4436 Discoverer.services != null && (Discoverer.services.size() > 0))
4438 // TODO: refactor to allow list of AbstractName/Handler bindings to
4440 // stored or retrieved from elsewhere
4441 // No MSAWS used any more:
4442 // Vector msaws = null; // (Vector)
4443 // Discoverer.services.get("MsaWS");
4444 Vector<ServiceHandle> secstrpr = Discoverer.services
4446 if (secstrpr != null)
4448 // Add any secondary structure prediction services
4449 for (int i = 0, j = secstrpr.size(); i < j; i++)
4451 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4452 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4453 .getServiceClient(sh);
4454 int p = secstrmenu.getItemCount();
4455 impl.attachWSMenuEntry(secstrmenu, me);
4456 int q = secstrmenu.getItemCount();
4457 for (int litm = p; litm < q; litm++)
4459 legacyItems.add(secstrmenu.getItem(litm));
4465 // Add all submenus in the order they should appear on the web
4467 wsmenu.add(msawsmenu);
4468 wsmenu.add(secstrmenu);
4469 wsmenu.add(dismenu);
4470 wsmenu.add(analymenu);
4471 // No search services yet
4472 // wsmenu.add(seqsrchmenu);
4474 javax.swing.SwingUtilities.invokeLater(new Runnable()
4481 webService.removeAll();
4482 // first, add discovered services onto the webservices menu
4483 if (wsmenu.size() > 0)
4485 for (int i = 0, j = wsmenu.size(); i < j; i++)
4487 webService.add(wsmenu.get(i));
4492 webService.add(me.webServiceNoServices);
4494 // TODO: move into separate menu builder class.
4496 // logic for 2.11.1.4 is
4497 // always look to see if there is a discover. if there isn't
4498 // we can't show any Jws2 services
4499 // if there are services available, show them - regardless of
4500 // the 'show JWS2 preference'
4501 // if the discoverer is running then say so
4502 // otherwise offer to trigger discovery if 'show JWS2' is not
4504 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4505 if (jws2servs != null)
4507 if (jws2servs.hasServices())
4509 jws2servs.attachWSMenuEntry(webService, me);
4510 for (Jws2Instance sv : jws2servs.getServices())
4512 if (sv.description.toLowerCase(Locale.ROOT)
4515 for (JMenuItem jmi : legacyItems)
4517 jmi.setVisible(false);
4523 if (jws2servs.isRunning())
4525 JMenuItem tm = new JMenuItem(
4526 "Still discovering JABA Services");
4527 tm.setEnabled(false);
4530 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4532 JMenuItem enableJws2 = new JMenuItem(
4533 "Discover Web Services");
4534 enableJws2.setToolTipText(
4535 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4536 enableJws2.setEnabled(true);
4537 enableJws2.addActionListener(new ActionListener()
4541 public void actionPerformed(ActionEvent e)
4543 // start service discoverer, but ignore preference
4544 Desktop.instance.startServiceDiscovery(false,
4548 webService.add(enableJws2);
4552 build_urlServiceMenu(me.webService);
4553 build_fetchdbmenu(webService);
4554 for (JMenu item : wsmenu)
4556 if (item.getItemCount() == 0)
4558 item.setEnabled(false);
4562 item.setEnabled(true);
4565 } catch (Exception e)
4568 "Exception during web service menu building process.",
4573 } catch (Exception e)
4576 buildingMenu = false;
4583 * construct any groupURL type service menu entries.
4587 protected void build_urlServiceMenu(JMenu webService)
4589 // TODO: remove this code when 2.7 is released
4590 // DEBUG - alignmentView
4592 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4593 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4595 * @Override public void actionPerformed(ActionEvent e) {
4596 * jalview.datamodel.AlignmentView
4597 * .testSelectionViews(af.viewport.getAlignment(),
4598 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4600 * }); webService.add(testAlView);
4602 // TODO: refactor to RestClient discoverer and merge menu entries for
4603 // rest-style services with other types of analysis/calculation service
4604 // SHmmr test client - still being implemented.
4605 // DEBUG - alignmentView
4607 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4610 client.attachWSMenuEntry(
4611 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4617 * Searches the alignment sequences for xRefs and builds the Show
4618 * Cross-References menu (formerly called Show Products), with database
4619 * sources for which cross-references are found (protein sources for a
4620 * nucleotide alignment and vice versa)
4622 * @return true if Show Cross-references menu should be enabled
4624 public boolean canShowProducts()
4626 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4627 AlignmentI dataset = viewport.getAlignment().getDataset();
4629 showProducts.removeAll();
4630 final boolean dna = viewport.getAlignment().isNucleotide();
4632 if (seqs == null || seqs.length == 0)
4634 // nothing to see here.
4638 boolean showp = false;
4641 List<String> ptypes = new CrossRef(seqs, dataset)
4642 .findXrefSourcesForSequences(dna);
4644 for (final String source : ptypes)
4647 final AlignFrame af = this;
4648 JMenuItem xtype = new JMenuItem(source);
4649 xtype.addActionListener(new ActionListener()
4652 public void actionPerformed(ActionEvent e)
4654 showProductsFor(af.viewport.getSequenceSelection(), dna,
4658 showProducts.add(xtype);
4660 showProducts.setVisible(showp);
4661 showProducts.setEnabled(showp);
4662 } catch (Exception e)
4665 "canShowProducts threw an exception - please report to help@jalview.org",
4673 * Finds and displays cross-references for the selected sequences (protein
4674 * products for nucleotide sequences, dna coding sequences for peptides).
4677 * the sequences to show cross-references for
4679 * true if from a nucleotide alignment (so showing proteins)
4681 * the database to show cross-references for
4683 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4684 final String source)
4686 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4691 * Construct and display a new frame containing the translation of this
4692 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4695 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4697 AlignmentI al = null;
4700 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4702 al = dna.translateCdna(codeTable);
4703 } catch (Exception ex)
4705 Console.error("Exception during translation. Please report this !",
4707 final String msg = MessageManager.getString(
4708 "label.error_when_translating_sequences_submit_bug_report");
4709 final String errorTitle = MessageManager
4710 .getString("label.implementation_error")
4711 + MessageManager.getString("label.translation_failed");
4712 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4713 JvOptionPane.ERROR_MESSAGE);
4716 if (al == null || al.getHeight() == 0)
4718 final String msg = MessageManager.getString(
4719 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4720 final String errorTitle = MessageManager
4721 .getString("label.translation_failed");
4722 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4723 JvOptionPane.WARNING_MESSAGE);
4727 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4728 af.setFileFormat(this.currentFileFormat);
4729 final String newTitle = MessageManager
4730 .formatMessage("label.translation_of_params", new Object[]
4731 { this.getTitle(), codeTable.getId() });
4732 af.setTitle(newTitle);
4733 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4735 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4736 viewport.openSplitFrame(af, new Alignment(seqs));
4740 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4747 * Set the file format
4751 public void setFileFormat(FileFormatI format)
4753 this.currentFileFormat = format;
4757 * Try to load a features file onto the alignment.
4760 * contents or path to retrieve file or a File object
4762 * access mode of file (see jalview.io.AlignFile)
4763 * @return true if features file was parsed correctly.
4765 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4768 return avc.parseFeaturesFile(file, sourceType,
4769 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4774 public void refreshFeatureUI(boolean enableIfNecessary)
4776 // note - currently this is only still here rather than in the controller
4777 // because of the featureSettings hard reference that is yet to be
4779 if (enableIfNecessary)
4781 viewport.setShowSequenceFeatures(true);
4782 showSeqFeatures.setSelected(true);
4788 public void dragEnter(DropTargetDragEvent evt)
4793 public void dragExit(DropTargetEvent evt)
4798 public void dragOver(DropTargetDragEvent evt)
4803 public void dropActionChanged(DropTargetDragEvent evt)
4808 public void drop(DropTargetDropEvent evt)
4810 // JAL-1552 - acceptDrop required before getTransferable call for
4811 // Java's Transferable for native dnd
4812 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4813 Transferable t = evt.getTransferable();
4815 final AlignFrame thisaf = this;
4816 final List<Object> files = new ArrayList<>();
4817 List<DataSourceType> protocols = new ArrayList<>();
4821 Desktop.transferFromDropTarget(files, protocols, evt, t);
4822 } catch (Exception e)
4824 e.printStackTrace();
4828 new Thread(new Runnable()
4835 // check to see if any of these files have names matching sequences
4838 SequenceIdMatcher idm = new SequenceIdMatcher(
4839 viewport.getAlignment().getSequencesArray());
4841 * Object[] { String,SequenceI}
4843 ArrayList<Object[]> filesmatched = new ArrayList<>();
4844 ArrayList<Object[]> filesnotmatched = new ArrayList<>();
4845 for (int i = 0; i < files.size(); i++)
4848 Object file = files.get(i);
4849 String fileName = file.toString();
4851 DataSourceType protocol = (file instanceof File
4852 ? DataSourceType.FILE
4853 : FormatAdapter.checkProtocol(fileName));
4854 if (protocol == DataSourceType.FILE)
4857 if (file instanceof File)
4860 Platform.cacheFileData(fl);
4864 fl = new File(fileName);
4866 pdbfn = fl.getName();
4868 else if (protocol == DataSourceType.URL)
4870 URL url = new URL(fileName);
4871 pdbfn = url.getFile();
4873 if (pdbfn.length() > 0)
4875 // attempt to find a match in the alignment
4876 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4877 int l = 0, c = pdbfn.indexOf(".");
4878 while (mtch == null && c != -1)
4883 } while ((c = pdbfn.indexOf(".", l)) > l);
4886 pdbfn = pdbfn.substring(0, l);
4888 mtch = idm.findAllIdMatches(pdbfn);
4890 FileFormatI type = null;
4895 type = new IdentifyFile().identify(file, protocol);
4896 } catch (Exception ex)
4900 if (type != null && type.isStructureFile())
4902 filesmatched.add(new Object[] { file, protocol, mtch });
4906 // File wasn't named like one of the sequences or wasn't a PDB
4908 filesnotmatched.add(new Object[] { file, protocol, type });
4912 if (filesmatched.size() > 0)
4914 boolean autoAssociate = Cache
4915 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4918 String msg = MessageManager.formatMessage(
4919 "label.automatically_associate_structure_files_with_sequences_same_name",
4921 { Integer.valueOf(filesmatched.size())
4923 String ttl = MessageManager.getString(
4924 "label.automatically_associate_structure_files_by_name");
4925 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4926 ttl, JvOptionPane.YES_NO_OPTION);
4927 autoAssociate = choice == JvOptionPane.YES_OPTION;
4931 for (Object[] fm : filesmatched)
4933 // try and associate
4934 // TODO: may want to set a standard ID naming formalism for
4935 // associating PDB files which have no IDs.
4936 for (SequenceI toassoc : (SequenceI[]) fm[2])
4938 PDBEntry pe = new AssociatePdbFileWithSeq()
4939 .associatePdbWithSeq(fm[0].toString(),
4940 (DataSourceType) fm[1], toassoc, false,
4944 jalview.bin.Console.errPrintln("Associated file : "
4945 + (fm[0].toString()) + " with "
4946 + toassoc.getDisplayId(true));
4950 // TODO: do we need to update overview ? only if features are
4952 alignPanel.paintAlignment(true, false);
4958 * add declined structures as sequences
4960 for (Object[] o : filesmatched)
4962 filesnotmatched.add(new Object[] { o[0], o[1] });
4966 if (filesnotmatched.size() > 0)
4968 if (assocfiles > 0 && (Cache.getDefault(
4969 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4970 || JvOptionPane.showConfirmDialog(thisaf,
4971 "<html>" + MessageManager.formatMessage(
4972 "label.ignore_unmatched_dropped_files_info",
4975 filesnotmatched.size())
4978 MessageManager.getString(
4979 "label.ignore_unmatched_dropped_files"),
4980 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4984 for (Object[] fn : filesnotmatched)
4986 loadJalviewDataFile(fn[0], (DataSourceType) fn[1],
4987 (FileFormatI) fn[2], null);
4991 } catch (Exception ex)
4993 ex.printStackTrace();
5001 * Attempt to load a "dropped" file or URL string, by testing in turn for
5003 * <li>an Annotation file</li>
5004 * <li>a JNet file</li>
5005 * <li>a features file</li>
5006 * <li>else try to interpret as an alignment file</li>
5010 * either a filename or a URL string.
5012 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
5013 FileFormatI format, SequenceI assocSeq)
5015 // BH 2018 was String file
5018 if (sourceType == null)
5020 sourceType = FormatAdapter.checkProtocol(file);
5022 // if the file isn't identified, or not positively identified as some
5023 // other filetype (PFAM is default unidentified alignment file type) then
5024 // try to parse as annotation.
5025 boolean isAnnotation = (format == null
5026 || FileFormat.Pfam.equals(format))
5027 ? new AnnotationFile().annotateAlignmentView(viewport,
5033 // first see if its a T-COFFEE score file
5034 TCoffeeScoreFile tcf = null;
5037 tcf = new TCoffeeScoreFile(file, sourceType);
5040 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5044 new TCoffeeColourScheme(viewport.getAlignment()));
5045 isAnnotation = true;
5046 setStatus(MessageManager.getString(
5047 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5051 // some problem - if no warning its probable that the ID matching
5052 // process didn't work
5053 JvOptionPane.showMessageDialog(Desktop.desktop,
5054 tcf.getWarningMessage() == null
5055 ? MessageManager.getString(
5056 "label.check_file_matches_sequence_ids_alignment")
5057 : tcf.getWarningMessage(),
5058 MessageManager.getString(
5059 "label.problem_reading_tcoffee_score_file"),
5060 JvOptionPane.WARNING_MESSAGE);
5067 } catch (Exception x)
5070 "Exception when processing data source as T-COFFEE score file",
5076 // try to see if its a JNet 'concise' style annotation file *before*
5078 // try to parse it as a features file
5081 format = new IdentifyFile().identify(file, sourceType);
5083 if (FileFormat.FeatureSettings == format)
5085 if (featureSettings != null)
5087 featureSettings.load(file, sourceType);
5091 FeatureSettings.loadFeatureSettingsFile(getFeatureRenderer(),
5092 fileObject, sourceType);
5095 else if (FileFormat.ScoreMatrix == format)
5097 ScoreMatrixFile sm = new ScoreMatrixFile(
5098 new FileParse(file, sourceType));
5100 // todo: i18n this message
5101 setStatus(MessageManager.formatMessage(
5102 "label.successfully_loaded_matrix",
5103 sm.getMatrixName()));
5105 else if (FileFormat.Jnet.equals(format))
5107 JPredFile predictions = new JPredFile(file, sourceType);
5108 new JnetAnnotationMaker();
5109 JnetAnnotationMaker.add_annotation(predictions,
5110 viewport.getAlignment(), 0, false);
5111 viewport.getAlignment().setupJPredAlignment();
5112 isAnnotation = true;
5114 // else if (IdentifyFile.FeaturesFile.equals(format))
5115 else if (FileFormat.Features.equals(format))
5117 if (parseFeaturesFile(file, sourceType))
5119 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5120 if (splitFrame != null)
5122 splitFrame.repaint();
5126 alignPanel.paintAlignment(true, true);
5132 new FileLoader().LoadFile(viewport, file, sourceType, format);
5139 alignPanel.adjustAnnotationHeight();
5140 viewport.updateSequenceIdColours();
5141 buildSortByAnnotationScoresMenu();
5142 alignPanel.paintAlignment(true, true);
5144 } catch (Exception ex)
5146 ex.printStackTrace();
5147 } catch (OutOfMemoryError oom)
5152 } catch (Exception x)
5157 + (sourceType != null
5158 ? (sourceType == DataSourceType.PASTE
5160 : "using " + sourceType + " from "
5164 ? "(parsing as '" + format + "' file)"
5166 oom, Desktop.desktop);
5171 * Method invoked by the ChangeListener on the tabbed pane, in other words
5172 * when a different tabbed pane is selected by the user or programmatically.
5175 public void tabSelectionChanged(int index)
5180 * update current Overview window title (if there is one)
5181 * to add view name "Original" if necessary
5183 alignPanel.setOverviewTitle(this);
5186 * switch panels and set Overview title (if there is one
5187 * because it was opened automatically)
5189 alignPanel = alignPanels.get(index);
5190 alignPanel.setOverviewTitle(this);
5192 viewport = alignPanel.av;
5193 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5194 setMenusFromViewport(viewport);
5195 if (featureSettings != null && featureSettings.isOpen()
5196 && featureSettings.fr.getViewport() != viewport)
5198 if (viewport.isShowSequenceFeatures())
5200 // refresh the featureSettings to reflect UI change
5201 showFeatureSettingsUI();
5205 // close feature settings for this view.
5206 featureSettings.close();
5213 * 'focus' any colour slider that is open to the selected viewport
5215 if (viewport.getConservationSelected())
5217 SliderPanel.setConservationSlider(alignPanel,
5218 viewport.getResidueShading(), alignPanel.getViewName());
5222 SliderPanel.hideConservationSlider();
5224 if (viewport.getAbovePIDThreshold())
5226 SliderPanel.setPIDSliderSource(alignPanel,
5227 viewport.getResidueShading(), alignPanel.getViewName());
5231 SliderPanel.hidePIDSlider();
5235 * If there is a frame linked to this one in a SplitPane, switch it to the
5236 * same view tab index. No infinite recursion of calls should happen, since
5237 * tabSelectionChanged() should not get invoked on setting the selected
5238 * index to an unchanged value. Guard against setting an invalid index
5239 * before the new view peer tab has been created.
5241 final AlignViewportI peer = viewport.getCodingComplement();
5244 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5245 .getAlignPanel().alignFrame;
5246 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5248 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5254 * On right mouse click on view tab, prompt for and set new view name.
5257 public void tabbedPane_mousePressed(MouseEvent e)
5259 if (e.isPopupTrigger())
5261 String msg = MessageManager.getString("label.enter_view_name");
5262 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5263 String reply = JvOptionPane.showInputDialog(msg, ttl);
5267 viewport.setViewName(reply);
5268 // TODO warn if reply is in getExistingViewNames()?
5269 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5274 public AlignViewport getCurrentView()
5280 * Open the dialog for regex description parsing.
5283 protected void extractScores_actionPerformed(ActionEvent e)
5285 ParseProperties pp = new jalview.analysis.ParseProperties(
5286 viewport.getAlignment());
5287 // TODO: verify regex and introduce GUI dialog for version 2.5
5288 // if (pp.getScoresFromDescription("col", "score column ",
5289 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5291 if (pp.getScoresFromDescription("description column",
5292 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5294 buildSortByAnnotationScoresMenu();
5302 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5306 protected void showDbRefs_actionPerformed(ActionEvent e)
5308 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5314 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5318 protected void showNpFeats_actionPerformed(ActionEvent e)
5320 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5324 * find the viewport amongst the tabs in this alignment frame and close that
5329 public boolean closeView(AlignViewportI av)
5333 this.closeMenuItem_actionPerformed(false);
5336 Component[] comp = tabbedPane.getComponents();
5337 for (int i = 0; comp != null && i < comp.length; i++)
5339 if (comp[i] instanceof AlignmentPanel)
5341 if (((AlignmentPanel) comp[i]).av == av)
5344 closeView((AlignmentPanel) comp[i]);
5352 protected void build_fetchdbmenu(JMenu webService)
5354 // Temporary hack - DBRef Fetcher always top level ws entry.
5355 // TODO We probably want to store a sequence database checklist in
5356 // preferences and have checkboxes.. rather than individual sources selected
5358 final JMenu rfetch = new JMenu(
5359 MessageManager.getString("action.fetch_db_references"));
5360 rfetch.setToolTipText(MessageManager.getString(
5361 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5362 webService.add(rfetch);
5364 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5365 MessageManager.getString("option.trim_retrieved_seqs"));
5366 trimrs.setToolTipText(
5367 MessageManager.getString("label.trim_retrieved_sequences"));
5369 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5370 trimrs.addActionListener(new ActionListener()
5373 public void actionPerformed(ActionEvent e)
5375 trimrs.setSelected(trimrs.isSelected());
5376 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5377 Boolean.valueOf(trimrs.isSelected()).toString());
5381 JMenuItem fetchr = new JMenuItem(
5382 MessageManager.getString("label.standard_databases"));
5383 fetchr.setToolTipText(
5384 MessageManager.getString("label.fetch_embl_uniprot"));
5385 fetchr.addActionListener(new ActionListener()
5389 public void actionPerformed(ActionEvent e)
5391 new Thread(new Runnable()
5396 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5397 .getAlignment().isNucleotide();
5398 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5399 alignPanel.av.getSequenceSelection(),
5400 alignPanel.alignFrame, null,
5401 alignPanel.alignFrame.featureSettings, isNucleotide);
5402 dbRefFetcher.addListener(new FetchFinishedListenerI()
5405 public void finished()
5408 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5409 .getFeatureSettingsModels())
5412 alignPanel.av.mergeFeaturesStyle(srcSettings);
5414 AlignFrame.this.setMenusForViewport();
5417 dbRefFetcher.fetchDBRefs(false);
5425 new Thread(new Runnable()
5430 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5431 .getSequenceFetcherSingleton();
5432 javax.swing.SwingUtilities.invokeLater(new Runnable()
5437 String[] dbclasses = sf.getNonAlignmentSources();
5438 List<DbSourceProxy> otherdb;
5439 JMenu dfetch = new JMenu();
5440 JMenu ifetch = new JMenu();
5441 JMenuItem fetchr = null;
5442 int comp = 0, icomp = 0, mcomp = 15;
5443 String mname = null;
5445 for (String dbclass : dbclasses)
5447 otherdb = sf.getSourceProxy(dbclass);
5448 // add a single entry for this class, or submenu allowing 'fetch
5450 if (otherdb == null || otherdb.size() < 1)
5456 mname = "From " + dbclass;
5458 if (otherdb.size() == 1)
5460 final DbSourceProxy[] dassource = otherdb
5461 .toArray(new DbSourceProxy[0]);
5462 DbSourceProxy src = otherdb.get(0);
5463 fetchr = new JMenuItem(src.getDbSource());
5464 fetchr.addActionListener(new ActionListener()
5468 public void actionPerformed(ActionEvent e)
5470 new Thread(new Runnable()
5476 boolean isNucleotide = alignPanel.alignFrame
5477 .getViewport().getAlignment()
5479 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5480 alignPanel.av.getSequenceSelection(),
5481 alignPanel.alignFrame, dassource,
5482 alignPanel.alignFrame.featureSettings,
5485 .addListener(new FetchFinishedListenerI()
5488 public void finished()
5490 FeatureSettingsModelI srcSettings = dassource[0]
5491 .getFeatureColourScheme();
5492 alignPanel.av.mergeFeaturesStyle(
5494 AlignFrame.this.setMenusForViewport();
5497 dbRefFetcher.fetchDBRefs(false);
5503 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5504 MessageManager.formatMessage(
5505 "label.fetch_retrieve_from", new Object[]
5506 { src.getDbName() })));
5512 final DbSourceProxy[] dassource = otherdb
5513 .toArray(new DbSourceProxy[0]);
5515 DbSourceProxy src = otherdb.get(0);
5516 fetchr = new JMenuItem(MessageManager
5517 .formatMessage("label.fetch_all_param", new Object[]
5518 { src.getDbSource() }));
5519 fetchr.addActionListener(new ActionListener()
5522 public void actionPerformed(ActionEvent e)
5524 new Thread(new Runnable()
5530 boolean isNucleotide = alignPanel.alignFrame
5531 .getViewport().getAlignment()
5533 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5534 alignPanel.av.getSequenceSelection(),
5535 alignPanel.alignFrame, dassource,
5536 alignPanel.alignFrame.featureSettings,
5539 .addListener(new FetchFinishedListenerI()
5542 public void finished()
5544 AlignFrame.this.setMenusForViewport();
5547 dbRefFetcher.fetchDBRefs(false);
5553 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5554 MessageManager.formatMessage(
5555 "label.fetch_retrieve_from_all_sources",
5557 { Integer.valueOf(otherdb.size())
5559 src.getDbSource(), src.getDbName() })));
5562 // and then build the rest of the individual menus
5563 ifetch = new JMenu(MessageManager.formatMessage(
5564 "label.source_from_db_source", new Object[]
5565 { src.getDbSource() }));
5567 String imname = null;
5569 for (DbSourceProxy sproxy : otherdb)
5571 String dbname = sproxy.getDbName();
5572 String sname = dbname.length() > 5
5573 ? dbname.substring(0, 5) + "..."
5575 String msname = dbname.length() > 10
5576 ? dbname.substring(0, 10) + "..."
5580 imname = MessageManager
5581 .formatMessage("label.from_msname", new Object[]
5584 fetchr = new JMenuItem(msname);
5585 final DbSourceProxy[] dassrc = { sproxy };
5586 fetchr.addActionListener(new ActionListener()
5590 public void actionPerformed(ActionEvent e)
5592 new Thread(new Runnable()
5598 boolean isNucleotide = alignPanel.alignFrame
5599 .getViewport().getAlignment()
5601 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5602 alignPanel.av.getSequenceSelection(),
5603 alignPanel.alignFrame, dassrc,
5604 alignPanel.alignFrame.featureSettings,
5607 .addListener(new FetchFinishedListenerI()
5610 public void finished()
5612 AlignFrame.this.setMenusForViewport();
5615 dbRefFetcher.fetchDBRefs(false);
5621 fetchr.setToolTipText(
5622 "<html>" + MessageManager.formatMessage(
5623 "label.fetch_retrieve_from", new Object[]
5627 if (++icomp >= mcomp || i == (otherdb.size()))
5629 ifetch.setText(MessageManager.formatMessage(
5630 "label.source_to_target", imname, sname));
5632 ifetch = new JMenu();
5640 if (comp >= mcomp || dbi >= (dbclasses.length))
5642 dfetch.setText(MessageManager.formatMessage(
5643 "label.source_to_target", mname, dbclass));
5645 dfetch = new JMenu();
5658 * Left justify the whole alignment.
5661 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5663 avc.justify_Region(true);
5667 * Right justify the whole alignment.
5670 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5672 avc.justify_Region(false);
5676 public void setShowSeqFeatures(boolean b)
5678 showSeqFeatures.setSelected(b);
5679 viewport.setShowSequenceFeatures(b);
5686 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5687 * awt.event.ActionEvent)
5690 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5692 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5693 alignPanel.paintAlignment(false, false);
5697 protected void updateShowSSRadioButtons(JMenu showSS, ButtonGroup ssButtonGroup){
5699 List<String> ssSources = new ArrayList<String>();
5700 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5701 .getAlignmentAnnotation();
5703 ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(anns);
5705 // Get the currently selected radio button
5706 String selectedButtonModelName = getSelectedRadioButtonDisplayString(ssButtonGroup);
5707 boolean selectedButtonModel = false;
5709 // Clear existing radio buttons
5711 JRadioButtonMenuItem radioButtonAllSS = new JRadioButtonMenuItem("All");
5712 radioButtonAllSS.addActionListener(new ActionListener() {
5714 public void actionPerformed(ActionEvent e) {
5715 showSS_actionPerformed("All");
5718 ssButtonGroup.add(radioButtonAllSS);
5719 showSS.add(radioButtonAllSS);
5721 JRadioButtonMenuItem radioButtonNoneSS = new JRadioButtonMenuItem("None");
5722 radioButtonNoneSS.addActionListener(new ActionListener() {
5724 public void actionPerformed(ActionEvent e) {
5725 showSS_actionPerformed("None");
5728 ssButtonGroup.add(radioButtonNoneSS);
5729 showSS.add(radioButtonNoneSS);
5730 showSS.addSeparator();
5732 for(String ssSource : ssSources) {
5734 JRadioButtonMenuItem radioButton = new JRadioButtonMenuItem(ssSource);
5735 radioButton.addActionListener(new ActionListener() {
5737 public void actionPerformed(ActionEvent e) {
5738 showSS_actionPerformed(ssSource);
5741 ssButtonGroup.add(radioButton);
5742 showSS.add(radioButton);
5744 // Check if this radio button's name matches the selected radio button's name
5745 if (ssSource.equals(selectedButtonModelName)) {
5746 radioButton.setSelected(true); // Select this radio button
5747 selectedButtonModel = true;
5752 if (selectedButtonModelName == "None") {
5753 // If no radio button was previously selected, select "All"
5754 ssButtonGroup.setSelected(radioButtonNoneSS.getModel(), true);
5755 selectedButtonModel = true;
5757 if (!selectedButtonModel) {
5758 // If no radio button was previously selected, select "All"
5759 ssButtonGroup.setSelected(radioButtonAllSS.getModel(), true);
5764 protected void showSS_actionPerformed(String ssSourceSelection){
5767 AlignmentAnnotation[] annotations = alignPanel.getAlignment()
5768 .getAlignmentAnnotation();
5770 for (AlignmentAnnotation aa: annotations) {
5772 for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
5774 if (label.equals(aa.label)) {
5778 if(ssSourceSelection == "All") {
5783 String ssSource = AlignmentUtils.extractSSSourceFromAnnotationDescription(aa);
5784 if(ssSource.equals(ssSourceSelection)) {
5796 List<AlignCalcWorkerI> workers = viewport.getCalcManager()
5797 .getRegisteredWorkersOfClass(SecondaryStructureConsensusThread.class);
5798 if (!workers.isEmpty()) {
5800 viewport.getCalcManager().startWorker(workers.remove(0));
5804 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5805 alignPanel.updateAnnotation();
5806 alignPanel.paintAlignment(true, true);
5812 protected String getSelectedRadioButtonDisplayString(ButtonGroup ssButtonGroup) {
5813 Enumeration<AbstractButton> buttons = ssButtonGroup.getElements();
5814 while (buttons.hasMoreElements()) {
5815 AbstractButton button = buttons.nextElement();
5816 if (button.isSelected()) {
5817 return button.getText();
5820 return null; // No radio button is selected
5827 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5831 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5833 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5834 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5842 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5843 * .event.ActionEvent)
5846 protected void showGroupConservation_actionPerformed(ActionEvent e)
5848 viewport.setShowGroupConservation(showGroupConservation.getState());
5849 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5856 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5857 * .event.ActionEvent)
5860 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5862 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5863 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5867 protected void showSSConsensusHistogram_actionPerformed(ActionEvent e)
5869 viewport.setShowSSConsensusHistogram(showSSConsensusHistogram.getState());
5870 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5877 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5878 * .event.ActionEvent)
5881 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5883 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5884 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5888 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5890 showSequenceLogo.setState(true);
5891 viewport.setShowSequenceLogo(true);
5892 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5893 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5897 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5899 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5906 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5907 * .event.ActionEvent)
5910 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5912 if (avc.makeGroupsFromSelection())
5914 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5915 alignPanel.updateAnnotation();
5916 alignPanel.paintAlignment(true,
5917 viewport.needToUpdateStructureViews());
5921 public void clearAlignmentSeqRep()
5923 // TODO refactor alignmentseqrep to controller
5924 if (viewport.getAlignment().hasSeqrep())
5926 viewport.getAlignment().setSeqrep(null);
5927 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5928 alignPanel.updateAnnotation();
5929 alignPanel.paintAlignment(true, true);
5934 protected void createGroup_actionPerformed(ActionEvent e)
5936 if (avc.createGroup())
5938 if (applyAutoAnnotationSettings.isSelected())
5940 alignPanel.updateAnnotation(true, false);
5942 alignPanel.alignmentChanged();
5947 protected void unGroup_actionPerformed(ActionEvent e)
5951 alignPanel.alignmentChanged();
5956 * make the given alignmentPanel the currently selected tab
5958 * @param alignmentPanel
5960 public void setDisplayedView(AlignmentPanel alignmentPanel)
5962 if (!viewport.getSequenceSetId()
5963 .equals(alignmentPanel.av.getSequenceSetId()))
5965 throw new Error(MessageManager.getString(
5966 "error.implementation_error_cannot_show_view_alignment_frame"));
5968 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5969 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5971 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5976 * Action on selection of menu options to Show or Hide annotations.
5979 * @param forSequences
5980 * update sequence-related annotations
5981 * @param forAlignment
5982 * update non-sequence-related annotations
5985 public void setAnnotationsVisibility(boolean visible,
5986 boolean forSequences, boolean forAlignment)
5988 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5989 .getAlignmentAnnotation();
5994 for (AlignmentAnnotation aa : anns)
5997 * don't display non-positional annotations on an alignment
5999 if (aa.annotations == null)
6003 boolean apply = (aa.sequenceRef == null && forAlignment)
6004 || (aa.sequenceRef != null && forSequences);
6007 aa.visible = visible;
6010 alignPanel.validateAnnotationDimensions(true);
6011 // TODO this triggers relayout of annotation panel - otherwise annotation
6012 // label height is different to panel height
6013 alignPanel.fontChanged();
6014 alignPanel.alignmentChanged();
6018 * Store selected annotation sort order for the view and repaint.
6021 protected void sortAnnotations_actionPerformed()
6023 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
6025 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
6026 alignPanel.paintAlignment(false, false);
6031 * @return alignment panels in this alignment frame
6033 public List<? extends AlignmentViewPanel> getAlignPanels()
6035 // alignPanels is never null
6036 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
6041 * Open a new alignment window, with the cDNA associated with this (protein)
6042 * alignment, aligned as is the protein.
6044 protected void viewAsCdna_actionPerformed()
6046 // TODO no longer a menu action - refactor as required
6047 final AlignmentI alignment = getViewport().getAlignment();
6048 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
6049 if (mappings == null)
6053 List<SequenceI> cdnaSeqs = new ArrayList<>();
6054 for (SequenceI aaSeq : alignment.getSequences())
6056 for (AlignedCodonFrame acf : mappings)
6058 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
6062 * There is a cDNA mapping for this protein sequence - add to new
6063 * alignment. It will share the same dataset sequence as other mapped
6064 * cDNA (no new mappings need to be created).
6066 final Sequence newSeq = new Sequence(dnaSeq);
6067 newSeq.setDatasetSequence(dnaSeq);
6068 cdnaSeqs.add(newSeq);
6072 if (cdnaSeqs.size() == 0)
6074 // show a warning dialog no mapped cDNA
6077 AlignmentI cdna = new Alignment(
6078 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
6079 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
6080 AlignFrame.DEFAULT_HEIGHT);
6081 cdna.alignAs(alignment);
6082 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
6084 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
6085 AlignFrame.DEFAULT_HEIGHT);
6089 * Set visibility of dna/protein complement view (available when shown in a
6095 protected void showComplement_actionPerformed(boolean show)
6097 SplitContainerI sf = getSplitViewContainer();
6100 sf.setComplementVisible(this, show);
6105 * Generate the reverse (optionally complemented) of the selected sequences,
6106 * and add them to the alignment
6109 protected void showReverse_actionPerformed(boolean complement)
6111 AlignmentI al = null;
6114 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
6115 al = dna.reverseCdna(complement);
6116 viewport.addAlignment(al, "");
6117 addHistoryItem(new EditCommand(
6118 MessageManager.getString("label.add_sequences"), Action.PASTE,
6119 al.getSequencesArray(), 0, al.getWidth(),
6120 viewport.getAlignment()));
6121 } catch (Exception ex)
6123 jalview.bin.Console.errPrintln(ex.getMessage());
6129 * Try to run a script in the Groovy console, having first ensured that this
6130 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
6131 * be targeted at this alignment.
6134 protected void runGroovy_actionPerformed()
6136 Jalview.getInstance().setCurrentAlignFrame(this);
6137 groovy.console.ui.Console console = Desktop.getGroovyConsole();
6138 if (console != null)
6142 console.setVariable(JalviewObjectI.currentAlFrameName, this);
6143 console.runScript();
6144 } catch (Exception ex)
6146 jalview.bin.Console.errPrintln((ex.toString()));
6147 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
6148 MessageManager.getString("label.couldnt_run_groovy_script"),
6149 MessageManager.getString("label.groovy_support_failed"),
6150 JvOptionPane.ERROR_MESSAGE);
6156 .errPrintln("Can't run Groovy script as console not found");
6161 * Hides columns containing (or not containing) a specified feature, provided
6162 * that would not leave all columns hidden
6164 * @param featureType
6165 * @param columnsContaining
6168 public boolean hideFeatureColumns(String featureType,
6169 boolean columnsContaining)
6171 boolean notForHiding = avc.markColumnsContainingFeatures(
6172 columnsContaining, false, false, featureType);
6175 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6176 false, featureType))
6178 getViewport().hideSelectedColumns();
6186 protected void selectHighlightedColumns_actionPerformed(
6187 ActionEvent actionEvent)
6189 // include key modifier check in case user selects from menu
6190 avc.markHighlightedColumns(
6191 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6192 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6193 | ActionEvent.CTRL_MASK)) != 0);
6197 protected void copyHighlightedColumns_actionPerformed(
6198 ActionEvent actionEvent)
6200 avc.copyHighlightedRegionsToClipboard();
6204 * Rebuilds the Colour menu, including any user-defined colours which have
6205 * been loaded either on startup or during the session
6207 public void buildColourMenu()
6209 colourMenu.removeAll();
6211 colourMenu.add(applyToAllGroups);
6212 colourMenu.add(textColour);
6213 colourMenu.addSeparator();
6215 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6216 viewport.getAlignment(), false);
6218 colourMenu.add(annotationColour);
6219 bg.add(annotationColour);
6220 colourMenu.addSeparator();
6221 colourMenu.add(conservationMenuItem);
6222 colourMenu.add(modifyConservation);
6223 colourMenu.add(abovePIDThreshold);
6224 colourMenu.add(modifyPID);
6226 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6227 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6231 * Open a dialog (if not already open) that allows the user to select and
6232 * calculate PCA or Tree analysis
6234 protected void openTreePcaDialog()
6236 if (alignPanel.getCalculationDialog() == null)
6238 new CalculationChooser(AlignFrame.this);
6243 protected void loadVcf_actionPerformed()
6245 JalviewFileChooser chooser = new JalviewFileChooser(
6246 Cache.getProperty("LAST_DIRECTORY"));
6247 chooser.setFileView(new JalviewFileView());
6248 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6249 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6250 final AlignFrame us = this;
6251 chooser.setResponseHandler(0, () -> {
6252 String choice = chooser.getSelectedFile().getPath();
6253 Cache.setProperty("LAST_DIRECTORY", choice);
6254 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6255 new VCFLoader(choice).loadVCF(seqs, us);
6257 chooser.showOpenDialog(null);
6261 private Rectangle lastFeatureSettingsBounds = null;
6264 public void setFeatureSettingsGeometry(Rectangle bounds)
6266 lastFeatureSettingsBounds = bounds;
6270 public Rectangle getFeatureSettingsGeometry()
6272 return lastFeatureSettingsBounds;
6277 class PrintThread extends Thread
6281 public PrintThread(AlignmentPanel ap)
6286 static PageFormat pf;
6291 PrinterJob printJob = PrinterJob.getPrinterJob();
6295 printJob.setPrintable(ap, pf);
6299 printJob.setPrintable(ap);
6302 if (printJob.printDialog())
6307 } catch (Exception PrintException)
6309 PrintException.printStackTrace();