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.ButtonModel;
67 import javax.swing.JCheckBoxMenuItem;
68 import javax.swing.JComponent;
69 import javax.swing.JEditorPane;
70 import javax.swing.JInternalFrame;
71 import javax.swing.JLabel;
72 import javax.swing.JLayeredPane;
73 import javax.swing.JMenu;
74 import javax.swing.JMenuItem;
75 import javax.swing.JPanel;
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 void registerHandler(final long id,
1001 final IProgressIndicatorHandler handler)
1003 if (progressBar != null)
1004 progressBar.registerHandler(id, handler);
1009 * @return true if any progress bars are still active
1012 public boolean operationInProgress()
1014 return progressBar == null ? false : progressBar.operationInProgress();
1018 * Sets the text of the status bar. Note that setting a null or empty value
1019 * will cause the status bar to be hidden, with possibly undesirable flicker
1020 * of the screen layout.
1023 public void setStatus(String text)
1025 statusBar.setText(text == null || text.isEmpty() ? " " : text);
1029 * Added so Castor Mapping file can obtain Jalview Version
1031 public String getVersion()
1033 return Cache.getProperty("VERSION");
1036 public FeatureRenderer getFeatureRenderer()
1038 return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1042 public void fetchSequence_actionPerformed()
1044 new SequenceFetcher(this);
1048 public void addFromFile_actionPerformed(ActionEvent e)
1050 Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1054 public void reload_actionPerformed(ActionEvent e)
1056 if (fileName != null)
1058 // TODO: JAL-1108 - ensure all associated frames are closed regardless of
1059 // originating file's format
1060 // TODO: work out how to recover feature settings for correct view(s) when
1061 // file is reloaded.
1062 if (FileFormat.Jalview.equals(currentFileFormat))
1064 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1065 for (int i = 0; i < frames.length; i++)
1067 if (frames[i] instanceof AlignFrame && frames[i] != this
1068 && ((AlignFrame) frames[i]).fileName != null
1069 && ((AlignFrame) frames[i]).fileName.equals(fileName))
1073 frames[i].setSelected(true);
1074 Desktop.instance.closeAssociatedWindows();
1075 } catch (java.beans.PropertyVetoException ex)
1081 Desktop.instance.closeAssociatedWindows();
1083 FileLoader loader = new FileLoader();
1084 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1085 ? DataSourceType.URL
1086 : DataSourceType.FILE;
1087 loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1091 Rectangle bounds = this.getBounds();
1093 FileLoader loader = new FileLoader();
1095 AlignFrame newframe = null;
1097 if (fileObject == null)
1100 DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1101 fileName) ? DataSourceType.URL : DataSourceType.FILE;
1102 newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1107 newframe = loader.LoadFileWaitTillLoaded(fileObject,
1108 DataSourceType.FILE, currentFileFormat);
1111 newframe.setBounds(bounds);
1112 if (featureSettings != null && featureSettings.isShowing())
1114 final Rectangle fspos = featureSettings.frame.getBounds();
1115 // TODO: need a 'show feature settings' function that takes bounds -
1116 // need to refactor Desktop.addFrame
1117 newframe.featureSettings_actionPerformed(null);
1118 final FeatureSettings nfs = newframe.featureSettings;
1119 SwingUtilities.invokeLater(new Runnable()
1124 nfs.frame.setBounds(fspos);
1127 this.featureSettings.close();
1128 this.featureSettings = null;
1130 this.closeMenuItem_actionPerformed(true);
1136 public void addFromText_actionPerformed(ActionEvent e)
1139 .inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1143 public void addFromURL_actionPerformed(ActionEvent e)
1145 Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1149 public void save_actionPerformed(ActionEvent e)
1151 if (fileName == null || (currentFileFormat == null)
1152 || HttpUtils.startsWithHttpOrHttps(fileName))
1154 saveAs_actionPerformed();
1158 saveAlignment(fileName, currentFileFormat);
1163 * Saves the alignment to a file with a name chosen by the user, if necessary
1164 * warning if a file would be overwritten
1167 public void saveAs_actionPerformed()
1169 String format = currentFileFormat == null ? null
1170 : currentFileFormat.getName();
1171 JalviewFileChooser chooser = JalviewFileChooser
1172 .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
1174 chooser.setFileView(new JalviewFileView());
1175 chooser.setDialogTitle(
1176 MessageManager.getString("label.save_alignment_to_file"));
1177 chooser.setToolTipText(MessageManager.getString("action.save"));
1179 int value = chooser.showSaveDialog(this);
1181 if (value != JalviewFileChooser.APPROVE_OPTION)
1185 currentFileFormat = chooser.getSelectedFormat();
1186 // todo is this (2005) test now obsolete - value is never null?
1187 while (currentFileFormat == null)
1189 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1191 .getString("label.select_file_format_before_saving"),
1192 MessageManager.getString("label.file_format_not_specified"),
1193 JvOptionPane.WARNING_MESSAGE);
1194 currentFileFormat = chooser.getSelectedFormat();
1195 value = chooser.showSaveDialog(this);
1196 if (value != JalviewFileChooser.APPROVE_OPTION)
1202 fileName = chooser.getSelectedFile().getPath();
1204 Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1205 Cache.setProperty("LAST_DIRECTORY", fileName);
1206 saveAlignment(fileName, currentFileFormat);
1209 boolean lastSaveSuccessful = false;
1211 FileFormatI lastFormatSaved;
1213 String lastFilenameSaved;
1216 * Raise a dialog or status message for the last call to saveAlignment.
1218 * @return true if last call to saveAlignment(file, format) was successful.
1220 public boolean isSaveAlignmentSuccessful()
1223 if (!lastSaveSuccessful)
1225 if (!Platform.isHeadless())
1227 JvOptionPane.showInternalMessageDialog(this, MessageManager
1228 .formatMessage("label.couldnt_save_file", new Object[]
1229 { lastFilenameSaved }),
1230 MessageManager.getString("label.error_saving_file"),
1231 JvOptionPane.WARNING_MESSAGE);
1235 Console.error(MessageManager
1236 .formatMessage("label.couldnt_save_file", new Object[]
1237 { lastFilenameSaved }));
1243 setStatus(MessageManager.formatMessage(
1244 "label.successfully_saved_to_file_in_format", new Object[]
1245 { lastFilenameSaved, lastFormatSaved }));
1248 return lastSaveSuccessful;
1252 * Saves the alignment to the specified file path, in the specified format,
1253 * which may be an alignment format, or Jalview project format. If the
1254 * alignment has hidden regions, or the format is one capable of including
1255 * non-sequence data (features, annotations, groups), then the user may be
1256 * prompted to specify what to include in the output.
1261 public void saveAlignment(String file, FileFormatI format)
1263 saveAlignment(file, format, false, false);
1266 public void saveAlignment(String file, FileFormatI format, boolean stdout,
1267 boolean forceBackup)
1269 lastSaveSuccessful = true;
1272 lastFilenameSaved = file;
1274 lastFormatSaved = format;
1276 if (FileFormat.Jalview.equals(format))
1278 String shortName = title;
1279 if (shortName.indexOf(File.separatorChar) > -1)
1281 shortName = shortName
1282 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
1284 // TODO deal with stdout=true
1285 lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1288 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1289 if (lastSaveSuccessful)
1291 this.getViewport().setSavedUpToDate(true);
1294 statusBar.setText(MessageManager.formatMessage(
1295 "label.successfully_saved_to_file_in_format", new Object[]
1301 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1302 Runnable cancelAction = () -> {
1303 lastSaveSuccessful = false;
1305 Runnable outputAction = () -> {
1306 // todo defer this to inside formatSequences (or later)
1307 AlignmentExportData exportData = viewport.getAlignExportData(options);
1308 String output = new FormatAdapter(alignPanel, options)
1309 .formatSequences(format, exportData.getAlignment(),
1310 exportData.getOmitHidden(),
1311 exportData.getStartEndPostions(),
1312 viewport.getAlignment().getHiddenColumns());
1315 lastSaveSuccessful = false;
1319 // create backupfiles object and get new temp filename destination
1320 boolean doBackup = forceBackup
1321 || (BackupFiles.getEnabled() && !stdout);
1322 BackupFiles backupfiles = null;
1325 Console.trace("ALIGNFRAME making backupfiles object for " + file);
1326 backupfiles = new BackupFiles(file);
1330 String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1332 Console.trace("ALIGNFRAME setting PrintWriter");
1333 PrintWriter out = stdout
1334 ? new PrintWriter(new OutputStreamWriter(System.out))
1335 : new PrintWriter(new FileWriter(tempFilePath));
1337 if (backupfiles != null)
1339 Console.trace("ALIGNFRAME about to write to temp file "
1340 + backupfiles.getTempFilePath());
1347 Console.trace("ALIGNFRAME about to close file");
1349 Console.trace("ALIGNFRAME closed file");
1351 AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
1354 statusBar.setText(MessageManager.formatMessage(
1355 "label.successfully_printed_to_stdout_in_format",
1357 { format.getName() }));
1361 statusBar.setText(MessageManager.formatMessage(
1362 "label.successfully_saved_to_file_in_format",
1364 { fileName, format.getName() }));
1366 lastSaveSuccessful = true;
1367 } catch (IOException e)
1369 lastSaveSuccessful = false;
1371 "ALIGNFRAME Something happened writing the temp file");
1372 Console.error(e.getMessage());
1373 Console.debug(Cache.getStackTraceString(e));
1374 } catch (Exception ex)
1376 lastSaveSuccessful = false;
1378 "ALIGNFRAME Something unexpected happened writing the temp file");
1379 Console.error(ex.getMessage());
1380 Console.debug(Cache.getStackTraceString(ex));
1385 backupfiles.setWriteSuccess(lastSaveSuccessful);
1386 Console.debug("ALIGNFRAME writing temp file was "
1387 + (lastSaveSuccessful ? "" : "NOT ") + "successful");
1388 // do the backup file roll and rename the temp file to actual file
1389 Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1390 lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1391 Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1392 + (lastSaveSuccessful ? "" : "un") + "successfully");
1395 Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1396 if (lastSaveSuccessful)
1398 AlignFrame.this.getViewport().setSavedUpToDate(true);
1404 * show dialog with export options if applicable; else just do it
1406 if (AlignExportOptions.isNeeded(viewport, format))
1408 AlignExportOptions choices = new AlignExportOptions(
1409 alignPanel.getAlignViewport(), format, options);
1410 choices.setResponseAction(0, outputAction);
1411 choices.setResponseAction(1, cancelAction);
1412 choices.showDialog();
1419 } catch (Exception e)
1421 // TODO Auto-generated catch block
1422 e.printStackTrace();
1428 * Outputs the alignment to textbox in the requested format, if necessary
1429 * first prompting the user for whether to include hidden regions or
1432 * @param fileFormatName
1435 protected void outputText_actionPerformed(String fileFormatName)
1437 FileFormatI fileFormat = FileFormats.getInstance()
1438 .forName(fileFormatName);
1439 AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1440 Runnable outputAction = () -> {
1441 // todo defer this to inside formatSequences (or later)
1442 AlignmentExportData exportData = viewport.getAlignExportData(options);
1443 CutAndPasteTransfer cap = new CutAndPasteTransfer();
1444 cap.setForInput(null);
1447 FileFormatI format = fileFormat;
1448 cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1449 format, exportData.getAlignment(),
1450 exportData.getOmitHidden(),
1451 exportData.getStartEndPostions(),
1452 viewport.getAlignment().getHiddenColumns()));
1453 Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1454 "label.alignment_output_command", new Object[]
1455 { fileFormat.getName() }), 600, 500);
1456 } catch (OutOfMemoryError oom)
1458 new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1465 * show dialog with export options if applicable; else just do it
1467 if (AlignExportOptions.isNeeded(viewport, fileFormat))
1469 AlignExportOptions choices = new AlignExportOptions(
1470 alignPanel.getAlignViewport(), fileFormat, options);
1471 choices.setResponseAction(0, outputAction);
1472 choices.showDialog();
1479 } catch (Exception e)
1481 e.printStackTrace();
1493 protected void htmlMenuItem_actionPerformed(ActionEvent e)
1495 HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1498 htmlSVG.exportHTML(null);
1499 } catch (ImageOutputException x)
1501 // report problem to console and raise dialog
1506 public void bioJSMenuItem_actionPerformed(ActionEvent e)
1508 BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1511 bjs.exportHTML(null);
1512 } catch (ImageOutputException x)
1514 // report problem to console and raise dialog
1518 public void createImageMap(File file, String image)
1522 alignPanel.makePNGImageMap(file, image);
1523 } catch (ImageOutputException x)
1525 // report problem to console and raise dialog
1530 public void createPNG_actionPerformed(ActionEvent e)
1535 } catch (ImageOutputException ioex)
1537 // raise dialog, and report via console
1542 public void createEPS_actionPerformed(ActionEvent e)
1547 } catch (ImageOutputException ioex)
1549 // raise dialog, and report via console
1555 public void createSVG_actionPerformed(ActionEvent e)
1560 } catch (ImageOutputException ioex)
1562 // raise dialog, and report via console
1568 * Creates a PNG image of the alignment and writes it to the given file. If
1569 * the file is null, the user is prompted to choose a file.
1573 public void createPNG(File f) throws ImageOutputException
1575 createPNG(f, null, BitmapImageSizing.defaultBitmapImageSizing());
1578 public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1579 throws ImageOutputException
1581 alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1585 * Creates an EPS image of the alignment and writes it to the given file. If
1586 * the file is null, the user is prompted to choose a file.
1590 public void createEPS(File f) throws ImageOutputException
1595 public void createEPS(File f, String renderer) throws ImageOutputException
1597 alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1601 * Creates an SVG image of the alignment and writes it to the given file. If
1602 * the file is null, the user is prompted to choose a file.
1606 public void createSVG(File f) throws ImageOutputException
1611 public void createSVG(File f, String renderer) throws ImageOutputException
1613 alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1617 public void pageSetup_actionPerformed(ActionEvent e)
1619 PrinterJob printJob = PrinterJob.getPrinterJob();
1620 PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1630 public void printMenuItem_actionPerformed(ActionEvent e)
1632 // Putting in a thread avoids Swing painting problems
1633 PrintThread thread = new PrintThread(alignPanel);
1638 public void exportFeatures_actionPerformed(ActionEvent e)
1640 new AnnotationExporter(alignPanel).exportFeatures();
1644 public void exportAnnotations_actionPerformed(ActionEvent e)
1646 new AnnotationExporter(alignPanel).exportAnnotations();
1650 public void associatedData_actionPerformed(ActionEvent e)
1652 final JalviewFileChooser chooser = new JalviewFileChooser(
1653 Cache.getProperty("LAST_DIRECTORY"));
1654 chooser.setFileView(new JalviewFileView());
1655 String tooltip = MessageManager
1656 .getString("label.load_jalview_annotations");
1657 chooser.setDialogTitle(tooltip);
1658 chooser.setToolTipText(tooltip);
1659 chooser.setResponseHandler(0, () -> {
1660 String choice = chooser.getSelectedFile().getPath();
1661 Cache.setProperty("LAST_DIRECTORY", choice);
1662 loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1665 chooser.showOpenDialog(this);
1669 * Close the current view or all views in the alignment frame. If the frame
1670 * only contains one view then the alignment will be removed from memory.
1672 * @param closeAllTabs
1675 public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1677 if (alignPanels != null && alignPanels.size() < 2)
1679 closeAllTabs = true;
1682 Desktop.closeModal(this);
1686 if (alignPanels != null)
1690 if (this.isClosed())
1692 // really close all the windows - otherwise wait till
1693 // setClosed(true) is called
1694 for (int i = 0; i < alignPanels.size(); i++)
1696 AlignmentPanel ap = alignPanels.get(i);
1703 closeView(alignPanel);
1708 if (featureSettings != null && featureSettings.isOpen())
1710 featureSettings.close();
1711 featureSettings = null;
1715 * this will raise an INTERNAL_FRAME_CLOSED event and this method will
1716 * be called recursively, with the frame now in 'closed' state
1718 this.setClosed(true);
1720 } catch (Exception ex)
1722 ex.printStackTrace();
1727 * Close the specified panel and close up tabs appropriately.
1729 * @param panelToClose
1731 public void closeView(AlignmentPanel panelToClose)
1733 int index = tabbedPane.getSelectedIndex();
1734 int closedindex = tabbedPane.indexOfComponent(panelToClose);
1735 alignPanels.remove(panelToClose);
1736 panelToClose.closePanel();
1737 panelToClose = null;
1739 tabbedPane.removeTabAt(closedindex);
1740 tabbedPane.validate();
1742 if (index > closedindex || index == tabbedPane.getTabCount())
1744 // modify currently selected tab index if necessary.
1748 this.tabSelectionChanged(index);
1754 void updateEditMenuBar()
1757 if (viewport.getHistoryList().size() > 0)
1759 undoMenuItem.setEnabled(true);
1760 CommandI command = viewport.getHistoryList().peek();
1761 undoMenuItem.setText(MessageManager
1762 .formatMessage("label.undo_command", new Object[]
1763 { command.getDescription() }));
1767 undoMenuItem.setEnabled(false);
1768 undoMenuItem.setText(MessageManager.getString("action.undo"));
1771 if (viewport.getRedoList().size() > 0)
1773 redoMenuItem.setEnabled(true);
1775 CommandI command = viewport.getRedoList().peek();
1776 redoMenuItem.setText(MessageManager
1777 .formatMessage("label.redo_command", new Object[]
1778 { command.getDescription() }));
1782 redoMenuItem.setEnabled(false);
1783 redoMenuItem.setText(MessageManager.getString("action.redo"));
1788 public void addHistoryItem(CommandI command)
1790 if (command.getSize() > 0)
1792 viewport.addToHistoryList(command);
1793 viewport.clearRedoList();
1794 updateEditMenuBar();
1795 viewport.updateHiddenColumns();
1796 // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1797 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1798 // viewport.getColumnSelection()
1799 // .getHiddenColumns().size() > 0);
1805 * @return alignment objects for all views
1807 public AlignmentI[] getViewAlignments()
1809 if (alignPanels != null)
1811 AlignmentI[] als = new AlignmentI[alignPanels.size()];
1813 for (AlignmentPanel ap : alignPanels)
1815 als[i++] = ap.av.getAlignment();
1819 if (viewport != null)
1821 return new AlignmentI[] { viewport.getAlignment() };
1833 protected void undoMenuItem_actionPerformed(ActionEvent e)
1835 if (viewport.getHistoryList().isEmpty())
1839 CommandI command = viewport.getHistoryList().pop();
1840 viewport.addToRedoList(command);
1841 command.undoCommand(getViewAlignments());
1843 AlignmentViewport originalSource = getOriginatingSource(command);
1844 updateEditMenuBar();
1846 if (originalSource != null)
1848 if (originalSource != viewport)
1851 "Implementation worry: mismatch of viewport origin for undo");
1853 originalSource.updateHiddenColumns();
1854 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1856 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1857 // viewport.getColumnSelection()
1858 // .getHiddenColumns().size() > 0);
1859 originalSource.firePropertyChange("alignment", null,
1860 originalSource.getAlignment().getSequences());
1871 protected void redoMenuItem_actionPerformed(ActionEvent e)
1873 if (viewport.getRedoList().size() < 1)
1878 CommandI command = viewport.getRedoList().pop();
1879 viewport.addToHistoryList(command);
1880 command.doCommand(getViewAlignments());
1882 AlignmentViewport originalSource = getOriginatingSource(command);
1883 updateEditMenuBar();
1885 if (originalSource != null)
1888 if (originalSource != viewport)
1891 "Implementation worry: mismatch of viewport origin for redo");
1893 originalSource.updateHiddenColumns();
1894 // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1896 // && viewport.getColumnSelection().getHiddenColumns() != null &&
1897 // viewport.getColumnSelection()
1898 // .getHiddenColumns().size() > 0);
1899 originalSource.firePropertyChange("alignment", null,
1900 originalSource.getAlignment().getSequences());
1904 AlignmentViewport getOriginatingSource(CommandI command)
1906 AlignmentViewport originalSource = null;
1907 // For sequence removal and addition, we need to fire
1908 // the property change event FROM the viewport where the
1909 // original alignment was altered
1910 AlignmentI al = null;
1911 if (command instanceof EditCommand)
1913 EditCommand editCommand = (EditCommand) command;
1914 al = editCommand.getAlignment();
1915 List<Component> comps = PaintRefresher.components
1916 .get(viewport.getSequenceSetId());
1918 for (Component comp : comps)
1920 if (comp instanceof AlignmentPanel)
1922 if (al == ((AlignmentPanel) comp).av.getAlignment())
1924 originalSource = ((AlignmentPanel) comp).av;
1931 if (originalSource == null)
1933 // The original view is closed, we must validate
1934 // the current view against the closed view first
1937 PaintRefresher.validateSequences(al, viewport.getAlignment());
1940 originalSource = viewport;
1943 return originalSource;
1947 * Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1948 * or the sequence under cursor in keyboard mode
1953 public void moveSelectedSequences(boolean up)
1955 SequenceGroup sg = viewport.getSelectionGroup();
1959 if (viewport.cursorMode)
1961 sg = new SequenceGroup();
1962 sg.addSequence(viewport.getAlignment().getSequenceAt(
1963 alignPanel.getSeqPanel().seqCanvas.cursorY), false);
1971 if (sg.getSize() < 1)
1976 // TODO: JAL-3733 - add an event to the undo buffer for this !
1978 viewport.getAlignment().moveSelectedSequencesByOne(sg,
1979 viewport.getHiddenRepSequences(), up);
1980 alignPanel.paintAlignment(true, false);
1983 synchronized void slideSequences(boolean right, int size)
1985 List<SequenceI> sg = new ArrayList<>();
1986 if (viewport.cursorMode)
1988 sg.add(viewport.getAlignment()
1989 .getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
1991 else if (viewport.getSelectionGroup() != null
1992 && viewport.getSelectionGroup().getSize() != viewport
1993 .getAlignment().getHeight())
1995 sg = viewport.getSelectionGroup()
1996 .getSequences(viewport.getHiddenRepSequences());
2004 List<SequenceI> invertGroup = new ArrayList<>();
2006 for (SequenceI seq : viewport.getAlignment().getSequences())
2008 if (!sg.contains(seq))
2010 invertGroup.add(seq);
2014 SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
2016 SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2017 for (int i = 0; i < invertGroup.size(); i++)
2019 seqs2[i] = invertGroup.get(i);
2022 SlideSequencesCommand ssc;
2025 ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2026 viewport.getGapCharacter());
2030 ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2031 viewport.getGapCharacter());
2034 int groupAdjustment = 0;
2035 if (ssc.getGapsInsertedBegin() && right)
2037 if (viewport.cursorMode)
2039 alignPanel.getSeqPanel().moveCursor(size, 0);
2043 groupAdjustment = size;
2046 else if (!ssc.getGapsInsertedBegin() && !right)
2048 if (viewport.cursorMode)
2050 alignPanel.getSeqPanel().moveCursor(-size, 0);
2054 groupAdjustment = -size;
2058 if (groupAdjustment != 0)
2060 viewport.getSelectionGroup().setStartRes(
2061 viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2062 viewport.getSelectionGroup().setEndRes(
2063 viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2067 * just extend the last slide command if compatible; but not if in
2068 * SplitFrame mode (to ensure all edits are broadcast - JAL-1802)
2070 boolean appendHistoryItem = false;
2071 Deque<CommandI> historyList = viewport.getHistoryList();
2072 boolean inSplitFrame = getSplitViewContainer() != null;
2073 if (!inSplitFrame && historyList != null && historyList.size() > 0
2074 && historyList.peek() instanceof SlideSequencesCommand)
2076 appendHistoryItem = ssc.appendSlideCommand(
2077 (SlideSequencesCommand) historyList.peek());
2080 if (!appendHistoryItem)
2082 addHistoryItem(ssc);
2095 protected void copy_actionPerformed()
2097 if (viewport.getSelectionGroup() == null)
2101 // TODO: preserve the ordering of displayed alignment annotation in any
2102 // internal paste (particularly sequence associated annotation)
2103 SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2104 String[] omitHidden = null;
2106 if (viewport.hasHiddenColumns())
2108 omitHidden = viewport.getViewAsString(true);
2111 String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2112 seqs, omitHidden, null);
2114 StringSelection ss = new StringSelection(output);
2118 jalview.gui.Desktop.internalCopy = true;
2119 // Its really worth setting the clipboard contents
2120 // to empty before setting the large StringSelection!!
2121 Toolkit.getDefaultToolkit().getSystemClipboard()
2122 .setContents(new StringSelection(""), null);
2124 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2126 } catch (OutOfMemoryError er)
2128 new OOMWarning("copying region", er);
2132 HiddenColumns hiddenColumns = null;
2133 if (viewport.hasHiddenColumns())
2135 int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2136 int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2138 // create new HiddenColumns object with copy of hidden regions
2139 // between startRes and endRes, offset by startRes
2140 hiddenColumns = new HiddenColumns(
2141 viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2142 hiddenCutoff, hiddenOffset);
2145 Desktop.jalviewClipboard = new Object[] { seqs,
2146 viewport.getAlignment().getDataset(), hiddenColumns };
2147 setStatus(MessageManager.formatMessage(
2148 "label.copied_sequences_to_clipboard", new Object[]
2149 { Integer.valueOf(seqs.length).toString() }));
2159 protected void pasteNew_actionPerformed(ActionEvent e)
2171 protected void pasteThis_actionPerformed(ActionEvent e)
2177 * Paste contents of Jalview clipboard
2179 * @param newAlignment
2180 * true to paste to a new alignment, otherwise add to this.
2182 void paste(boolean newAlignment)
2184 boolean externalPaste = true;
2187 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2188 Transferable contents = c.getContents(this);
2190 if (contents == null)
2199 str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2200 if (str.length() < 1)
2205 format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2207 } catch (OutOfMemoryError er)
2209 new OOMWarning("Out of memory pasting sequences!!", er);
2213 SequenceI[] sequences;
2214 boolean annotationAdded = false;
2215 AlignmentI alignment = null;
2217 if (Desktop.jalviewClipboard != null)
2219 // The clipboard was filled from within Jalview, we must use the
2221 // And dataset from the copied alignment
2222 SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2223 // be doubly sure that we create *new* sequence objects.
2224 sequences = new SequenceI[newseq.length];
2225 for (int i = 0; i < newseq.length; i++)
2227 sequences[i] = new Sequence(newseq[i]);
2229 alignment = new Alignment(sequences);
2230 externalPaste = false;
2234 // parse the clipboard as an alignment.
2235 alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2237 sequences = alignment.getSequencesArray();
2241 ArrayList<Integer> newGraphGroups = new ArrayList<>();
2247 if (Desktop.jalviewClipboard != null)
2249 // dataset is inherited
2250 alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2254 // new dataset is constructed
2255 alignment.setDataset(null);
2257 alwidth = alignment.getWidth() + 1;
2261 AlignmentI pastedal = alignment; // preserve pasted alignment object
2262 // Add pasted sequences and dataset into existing alignment.
2263 alignment = viewport.getAlignment();
2264 alwidth = alignment.getWidth() + 1;
2265 // decide if we need to import sequences from an existing dataset
2266 boolean importDs = Desktop.jalviewClipboard != null
2267 && Desktop.jalviewClipboard[1] != alignment.getDataset();
2268 // importDs==true instructs us to copy over new dataset sequences from
2269 // an existing alignment
2270 Vector<SequenceI> newDs = (importDs) ? new Vector<>() : null; // used to
2272 // minimum dataset set
2274 for (int i = 0; i < sequences.length; i++)
2278 newDs.addElement(null);
2280 SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2282 if (importDs && ds != null)
2284 if (!newDs.contains(ds))
2286 newDs.setElementAt(ds, i);
2287 ds = new Sequence(ds);
2288 // update with new dataset sequence
2289 sequences[i].setDatasetSequence(ds);
2293 ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2298 // copy and derive new dataset sequence
2299 sequences[i] = sequences[i].deriveSequence();
2300 alignment.getDataset()
2301 .addSequence(sequences[i].getDatasetSequence());
2302 // TODO: avoid creation of duplicate dataset sequences with a
2303 // 'contains' method using SequenceI.equals()/SequenceI.contains()
2305 alignment.addSequence(sequences[i]); // merges dataset
2309 newDs.clear(); // tidy up
2311 if (alignment.getAlignmentAnnotation() != null)
2313 for (AlignmentAnnotation alan : alignment
2314 .getAlignmentAnnotation())
2316 if (alan.graphGroup > fgroup)
2318 fgroup = alan.graphGroup;
2322 if (pastedal.getAlignmentAnnotation() != null)
2324 // Add any annotation attached to alignment.
2325 AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2326 for (int i = 0; i < alann.length; i++)
2328 annotationAdded = true;
2329 if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2331 AlignmentAnnotation newann = new AlignmentAnnotation(
2333 if (newann.graphGroup > -1)
2335 if (newGraphGroups.size() <= newann.graphGroup
2336 || newGraphGroups.get(newann.graphGroup) == null)
2338 for (int q = newGraphGroups
2339 .size(); q <= newann.graphGroup; q++)
2341 newGraphGroups.add(q, null);
2343 newGraphGroups.set(newann.graphGroup,
2344 Integer.valueOf(++fgroup));
2346 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2350 newann.padAnnotation(alwidth);
2351 alignment.addAnnotation(newann);
2361 addHistoryItem(new EditCommand(
2362 MessageManager.getString("label.add_sequences"),
2363 Action.PASTE, sequences, 0, alignment.getWidth(),
2366 // Add any annotations attached to sequences
2367 for (int i = 0; i < sequences.length; i++)
2369 if (sequences[i].getAnnotation() != null)
2371 AlignmentAnnotation newann;
2372 for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2374 annotationAdded = true;
2375 newann = sequences[i].getAnnotation()[a];
2376 newann.adjustForAlignment();
2377 newann.padAnnotation(alwidth);
2378 if (newann.graphGroup > -1)
2380 if (newann.graphGroup > -1)
2382 if (newGraphGroups.size() <= newann.graphGroup
2383 || newGraphGroups.get(newann.graphGroup) == null)
2385 for (int q = newGraphGroups
2386 .size(); q <= newann.graphGroup; q++)
2388 newGraphGroups.add(q, null);
2390 newGraphGroups.set(newann.graphGroup,
2391 Integer.valueOf(++fgroup));
2393 newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2397 // annotation was duplicated earlier
2398 alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2399 // take care of contact matrix too
2400 ContactMatrixI cm = sequences[i]
2401 .getContactMatrixFor(sequences[i].getAnnotation()[a]);
2404 alignment.addContactListFor(sequences[i].getAnnotation()[a],
2408 alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2416 // propagate alignment changed.
2417 viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2418 if (annotationAdded)
2420 // Duplicate sequence annotation in all views.
2421 AlignmentI[] alview = this.getViewAlignments();
2422 for (int i = 0; i < sequences.length; i++)
2424 AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2429 for (int avnum = 0; avnum < alview.length; avnum++)
2431 if (alview[avnum] != alignment)
2433 // duplicate in a view other than the one with input focus
2434 int avwidth = alview[avnum].getWidth() + 1;
2435 // this relies on sann being preserved after we
2436 // modify the sequence's annotation array for each duplication
2437 for (int a = 0; a < sann.length; a++)
2439 AlignmentAnnotation newann = new AlignmentAnnotation(
2441 sequences[i].addAlignmentAnnotation(newann);
2442 newann.padAnnotation(avwidth);
2443 alview[avnum].addAnnotation(newann); // annotation was
2444 // duplicated earlier
2445 // TODO JAL-1145 graphGroups are not updated for sequence
2446 // annotation added to several views. This may cause
2448 alview[avnum].setAnnotationIndex(newann, a);
2453 buildSortByAnnotationScoresMenu();
2455 viewport.firePropertyChange("alignment", null,
2456 alignment.getSequences());
2457 if (alignPanels != null)
2459 for (AlignmentPanel ap : alignPanels)
2461 ap.validateAnnotationDimensions(false);
2466 alignPanel.validateAnnotationDimensions(false);
2472 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2474 String newtitle = new String("Copied sequences");
2476 if (Desktop.jalviewClipboard != null
2477 && Desktop.jalviewClipboard[2] != null)
2479 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2480 af.viewport.setHiddenColumns(hc);
2483 // >>>This is a fix for the moment, until a better solution is
2485 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2486 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2487 .getFeatureRenderer());
2489 // TODO: maintain provenance of an alignment, rather than just make the
2490 // title a concatenation of operations.
2493 if (title.startsWith("Copied sequences"))
2499 newtitle = newtitle.concat("- from " + title);
2504 newtitle = new String("Pasted sequences");
2507 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2512 } catch (Exception ex)
2514 ex.printStackTrace();
2515 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2516 // could be anything being pasted in here
2522 protected void expand_newalign(ActionEvent e)
2526 AlignmentI alignment = AlignmentUtils
2527 .expandContext(getViewport().getAlignment(), -1);
2528 AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2530 String newtitle = new String("Flanking alignment");
2532 if (Desktop.jalviewClipboard != null
2533 && Desktop.jalviewClipboard[2] != null)
2535 HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2536 af.viewport.setHiddenColumns(hc);
2539 // >>>This is a fix for the moment, until a better solution is
2541 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2542 .transferSettings(alignPanel.getSeqPanel().seqCanvas
2543 .getFeatureRenderer());
2545 // TODO: maintain provenance of an alignment, rather than just make the
2546 // title a concatenation of operations.
2548 if (title.startsWith("Copied sequences"))
2554 newtitle = newtitle.concat("- from " + title);
2558 Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2560 } catch (Exception ex)
2562 ex.printStackTrace();
2563 jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2564 // could be anything being pasted in here
2565 } catch (OutOfMemoryError oom)
2567 new OOMWarning("Viewing flanking region of alignment", oom);
2572 * Action Cut (delete and copy) the selected region
2575 protected void cut_actionPerformed()
2577 copy_actionPerformed();
2578 delete_actionPerformed();
2582 * Performs menu option to Delete the currently selected region
2585 protected void delete_actionPerformed()
2588 SequenceGroup sg = viewport.getSelectionGroup();
2594 Runnable okAction = () -> {
2595 SequenceI[] cut = sg.getSequences()
2596 .toArray(new SequenceI[sg.getSize()]);
2598 addHistoryItem(new EditCommand(
2599 MessageManager.getString("label.cut_sequences"), Action.CUT,
2600 cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2601 viewport.getAlignment()));
2603 viewport.setSelectionGroup(null);
2604 viewport.sendSelection();
2605 viewport.getAlignment().deleteGroup(sg);
2607 viewport.firePropertyChange("alignment", null,
2608 viewport.getAlignment().getSequences());
2609 if (viewport.getAlignment().getHeight() < 1)
2613 AlignFrame.this.setClosed(true);
2614 } catch (Exception ex)
2621 * If the cut affects all sequences, prompt for confirmation
2623 boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2625 boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2626 + 1) == viewport.getAlignment().getWidth()) ? true : false;
2627 if (wholeHeight && wholeWidth)
2629 JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2630 dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2631 Object[] options = new Object[] {
2632 MessageManager.getString("action.ok"),
2633 MessageManager.getString("action.cancel") };
2634 dialog.showDialog(MessageManager.getString("warn.delete_all"),
2635 MessageManager.getString("label.delete_all"),
2636 JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2637 options, options[0]);
2644 } catch (Exception e)
2646 e.printStackTrace();
2658 protected void deleteGroups_actionPerformed(ActionEvent e)
2660 if (avc.deleteGroups())
2662 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2663 alignPanel.updateAnnotation();
2664 alignPanel.paintAlignment(true, true);
2675 public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2677 SequenceGroup sg = new SequenceGroup(
2678 viewport.getAlignment().getSequences());
2680 sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2681 viewport.setSelectionGroup(sg);
2682 viewport.isSelectionGroupChanged(true);
2683 viewport.sendSelection();
2684 // JAL-2034 - should delegate to
2685 // alignPanel to decide if overview needs
2687 alignPanel.paintAlignment(false, false);
2688 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2698 public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2700 if (viewport.cursorMode)
2702 alignPanel.getSeqPanel().keyboardNo1 = null;
2703 alignPanel.getSeqPanel().keyboardNo2 = null;
2705 viewport.setSelectionGroup(null);
2706 viewport.getColumnSelection().clear();
2707 viewport.setSearchResults(null);
2708 alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2709 // JAL-2034 - should delegate to
2710 // alignPanel to decide if overview needs
2712 alignPanel.paintAlignment(false, false);
2713 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2714 viewport.sendSelection();
2724 public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2726 SequenceGroup sg = viewport.getSelectionGroup();
2730 selectAllSequenceMenuItem_actionPerformed(null);
2735 for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2737 sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2739 // JAL-2034 - should delegate to
2740 // alignPanel to decide if overview needs
2743 alignPanel.paintAlignment(true, false);
2744 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2745 viewport.sendSelection();
2749 public void invertColSel_actionPerformed(ActionEvent e)
2751 viewport.invertColumnSelection();
2752 alignPanel.paintAlignment(true, false);
2753 PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2754 viewport.sendSelection();
2764 public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2766 trimAlignment(true);
2776 public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2778 trimAlignment(false);
2781 void trimAlignment(boolean trimLeft)
2783 ColumnSelection colSel = viewport.getColumnSelection();
2786 if (!colSel.isEmpty())
2790 column = colSel.getMin();
2794 column = colSel.getMax();
2798 if (viewport.getSelectionGroup() != null)
2800 seqs = viewport.getSelectionGroup()
2801 .getSequencesAsArray(viewport.getHiddenRepSequences());
2805 seqs = viewport.getAlignment().getSequencesArray();
2808 TrimRegionCommand trimRegion;
2811 trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2812 column, viewport.getAlignment());
2813 viewport.getRanges().setStartRes(0);
2817 trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2818 column, viewport.getAlignment());
2821 setStatus(MessageManager.formatMessage("label.removed_columns",
2823 { Integer.valueOf(trimRegion.getSize()).toString() }));
2825 addHistoryItem(trimRegion);
2827 for (SequenceGroup sg : viewport.getAlignment().getGroups())
2829 if ((trimLeft && !sg.adjustForRemoveLeft(column))
2830 || (!trimLeft && !sg.adjustForRemoveRight(column)))
2832 viewport.getAlignment().deleteGroup(sg);
2836 viewport.firePropertyChange("alignment", null,
2837 viewport.getAlignment().getSequences());
2848 public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2850 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2853 if (viewport.getSelectionGroup() != null)
2855 seqs = viewport.getSelectionGroup()
2856 .getSequencesAsArray(viewport.getHiddenRepSequences());
2857 start = viewport.getSelectionGroup().getStartRes();
2858 end = viewport.getSelectionGroup().getEndRes();
2862 seqs = viewport.getAlignment().getSequencesArray();
2865 RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2866 "Remove Gapped Columns", seqs, start, end,
2867 viewport.getAlignment());
2869 addHistoryItem(removeGapCols);
2871 setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2873 { Integer.valueOf(removeGapCols.getSize()).toString() }));
2875 // This is to maintain viewport position on first residue
2876 // of first sequence
2877 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2878 ViewportRanges ranges = viewport.getRanges();
2879 int startRes = seq.findPosition(ranges.getStartRes());
2880 // ShiftList shifts;
2881 // viewport.getAlignment().removeGaps(shifts=new ShiftList());
2882 // edit.alColumnChanges=shifts.getInverse();
2883 // if (viewport.hasHiddenColumns)
2884 // viewport.getColumnSelection().compensateForEdits(shifts);
2885 ranges.setStartRes(seq.findIndex(startRes) - 1);
2886 viewport.firePropertyChange("alignment", null,
2887 viewport.getAlignment().getSequences());
2898 public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2900 int start = 0, end = viewport.getAlignment().getWidth() - 1;
2903 if (viewport.getSelectionGroup() != null)
2905 seqs = viewport.getSelectionGroup()
2906 .getSequencesAsArray(viewport.getHiddenRepSequences());
2907 start = viewport.getSelectionGroup().getStartRes();
2908 end = viewport.getSelectionGroup().getEndRes();
2912 seqs = viewport.getAlignment().getSequencesArray();
2915 // This is to maintain viewport position on first residue
2916 // of first sequence
2917 SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2918 int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2920 addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2921 viewport.getAlignment()));
2923 viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2925 viewport.firePropertyChange("alignment", null,
2926 viewport.getAlignment().getSequences());
2937 public void padGapsMenuitem_actionPerformed(ActionEvent e)
2939 viewport.setPadGaps(padGapsMenuitem.isSelected());
2940 viewport.firePropertyChange("alignment", null,
2941 viewport.getAlignment().getSequences());
2945 * Opens a Finder dialog
2950 public void findMenuItem_actionPerformed(ActionEvent e)
2952 new Finder(alignPanel, false, null);
2956 * Create a new view of the current alignment.
2959 public void newView_actionPerformed(ActionEvent e)
2961 newView(null, true);
2965 * Creates and shows a new view of the current alignment.
2968 * title of newly created view; if null, one will be generated
2969 * @param copyAnnotation
2970 * if true then duplicate all annnotation, groups and settings
2971 * @return new alignment panel, already displayed.
2973 public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
2976 * Create a new AlignmentPanel (with its own, new Viewport)
2978 AlignmentPanel newap = new jalview.project.Jalview2XML()
2979 .copyAlignPanel(alignPanel);
2980 if (!copyAnnotation)
2983 * remove all groups and annotation except for the automatic stuff
2985 newap.av.getAlignment().deleteAllGroups();
2986 newap.av.getAlignment().deleteAllAnnotations(false);
2989 newap.av.setGatherViewsHere(false);
2991 if (viewport.getViewName() == null)
2993 viewport.setViewName(
2994 MessageManager.getString("label.view_name_original"));
2998 * Views share the same edits undo and redo stacks
3000 newap.av.setHistoryList(viewport.getHistoryList());
3001 newap.av.setRedoList(viewport.getRedoList());
3004 * copy any visualisation settings that are not saved in the project
3006 newap.av.setColourAppliesToAllGroups(
3007 viewport.getColourAppliesToAllGroups());
3010 * Views share the same mappings; need to deregister any new mappings
3011 * created by copyAlignPanel, and register the new reference to the shared
3014 newap.av.replaceMappings(viewport.getAlignment());
3017 * start up cDNA consensus (if applicable) now mappings are in place
3019 if (newap.av.initComplementConsensus())
3021 newap.refresh(true); // adjust layout of annotations
3024 newap.av.setViewName(getNewViewName(viewTitle));
3026 addAlignmentPanel(newap, true);
3027 newap.alignmentChanged();
3029 if (alignPanels.size() == 2)
3031 viewport.setGatherViewsHere(true);
3033 tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3039 * Make a new name for the view, ensuring it is unique within the current
3040 * sequenceSetId. (This used to be essential for Jalview Project archives, but
3041 * these now use viewId. Unique view names are still desirable for usability.)
3046 protected String getNewViewName(String viewTitle)
3048 int index = Desktop.getViewCount(viewport.getSequenceSetId());
3049 boolean addFirstIndex = false;
3050 if (viewTitle == null || viewTitle.trim().length() == 0)
3052 viewTitle = MessageManager.getString("action.view");
3053 addFirstIndex = true;
3057 index = 1;// we count from 1 if given a specific name
3059 String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3061 List<Component> comps = PaintRefresher.components
3062 .get(viewport.getSequenceSetId());
3064 List<String> existingNames = getExistingViewNames(comps);
3066 while (existingNames.contains(newViewName))
3068 newViewName = viewTitle + " " + (++index);
3074 * Returns a list of distinct view names found in the given list of
3075 * components. View names are held on the viewport of an AlignmentPanel.
3080 protected List<String> getExistingViewNames(List<Component> comps)
3082 List<String> existingNames = new ArrayList<>();
3083 for (Component comp : comps)
3085 if (comp instanceof AlignmentPanel)
3087 AlignmentPanel ap = (AlignmentPanel) comp;
3088 if (!existingNames.contains(ap.av.getViewName()))
3090 existingNames.add(ap.av.getViewName());
3094 return existingNames;
3098 * Explode tabbed views into separate windows.
3101 public void expandViews_actionPerformed(ActionEvent e)
3103 Desktop.explodeViews(this);
3107 * Gather views in separate windows back into a tabbed presentation.
3110 public void gatherViews_actionPerformed(ActionEvent e)
3112 Desktop.instance.gatherViews(this);
3122 public void font_actionPerformed(ActionEvent e)
3124 new FontChooser(alignPanel);
3134 protected void seqLimit_actionPerformed(ActionEvent e)
3136 viewport.setShowJVSuffix(seqLimits.isSelected());
3138 alignPanel.getIdPanel().getIdCanvas()
3139 .setPreferredSize(alignPanel.calculateIdWidth());
3140 alignPanel.paintAlignment(true, false);
3144 public void idRightAlign_actionPerformed(ActionEvent e)
3146 viewport.setRightAlignIds(idRightAlign.isSelected());
3147 alignPanel.paintAlignment(false, false);
3151 public void centreColumnLabels_actionPerformed(ActionEvent e)
3153 viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3154 alignPanel.paintAlignment(false, false);
3160 * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3163 protected void followHighlight_actionPerformed()
3166 * Set the 'follow' flag on the Viewport (and scroll to position if now
3169 final boolean state = this.followHighlightMenuItem.getState();
3170 viewport.setFollowHighlight(state);
3173 alignPanel.scrollToPosition(viewport.getSearchResults());
3184 protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3186 viewport.setColourText(colourTextMenuItem.isSelected());
3187 alignPanel.paintAlignment(false, false);
3197 public void wrapMenuItem_actionPerformed(ActionEvent e)
3199 setWrapFormat(wrapMenuItem.isSelected(), false);
3202 public void setWrapFormat(boolean b, boolean setMenuItem)
3204 scaleAbove.setVisible(b);
3205 scaleLeft.setVisible(b);
3206 scaleRight.setVisible(b);
3207 viewport.setWrapAlignment(b);
3208 alignPanel.updateLayout();
3211 wrapMenuItem.setSelected(b);
3216 public void showAllSeqs_actionPerformed(ActionEvent e)
3218 viewport.showAllHiddenSeqs();
3222 public void showAllColumns_actionPerformed(ActionEvent e)
3224 viewport.showAllHiddenColumns();
3225 alignPanel.paintAlignment(true, true);
3226 viewport.sendSelection();
3230 public void hideSelSequences_actionPerformed(ActionEvent e)
3232 viewport.hideAllSelectedSeqs();
3236 * called by key handler and the hide all/show all menu items
3241 protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3244 boolean hide = false;
3245 SequenceGroup sg = viewport.getSelectionGroup();
3246 if (!toggleSeqs && !toggleCols)
3248 // Hide everything by the current selection - this is a hack - we do the
3249 // invert and then hide
3250 // first check that there will be visible columns after the invert.
3251 if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3252 && sg.getStartRes() <= sg.getEndRes()))
3254 // now invert the sequence set, if required - empty selection implies
3255 // that no hiding is required.
3258 invertSequenceMenuItem_actionPerformed(null);
3259 sg = viewport.getSelectionGroup();
3263 viewport.expandColSelection(sg, true);
3264 // finally invert the column selection and get the new sequence
3266 invertColSel_actionPerformed(null);
3273 if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3275 hideSelSequences_actionPerformed(null);
3278 else if (!(toggleCols && viewport.hasSelectedColumns()))
3280 showAllSeqs_actionPerformed(null);
3286 if (viewport.hasSelectedColumns())
3288 hideSelColumns_actionPerformed(null);
3291 viewport.setSelectionGroup(sg);
3296 showAllColumns_actionPerformed(null);
3305 * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3306 * event.ActionEvent)
3309 public void hideAllButSelection_actionPerformed(ActionEvent e)
3311 toggleHiddenRegions(false, false);
3312 viewport.sendSelection();
3319 * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3323 public void hideAllSelection_actionPerformed(ActionEvent e)
3325 SequenceGroup sg = viewport.getSelectionGroup();
3326 viewport.expandColSelection(sg, false);
3327 viewport.hideAllSelectedSeqs();
3328 viewport.hideSelectedColumns();
3329 alignPanel.updateLayout();
3330 alignPanel.paintAlignment(true, true);
3331 viewport.sendSelection();
3338 * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3342 public void showAllhidden_actionPerformed(ActionEvent e)
3344 viewport.showAllHiddenColumns();
3345 viewport.showAllHiddenSeqs();
3346 alignPanel.paintAlignment(true, true);
3347 viewport.sendSelection();
3351 public void hideSelColumns_actionPerformed(ActionEvent e)
3353 viewport.hideSelectedColumns();
3354 alignPanel.updateLayout();
3355 alignPanel.paintAlignment(true, true);
3356 viewport.sendSelection();
3360 public void hiddenMarkers_actionPerformed(ActionEvent e)
3362 viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3373 protected void scaleAbove_actionPerformed(ActionEvent e)
3375 viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3376 alignPanel.updateLayout();
3377 alignPanel.paintAlignment(true, false);
3387 protected void scaleLeft_actionPerformed(ActionEvent e)
3389 viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3390 alignPanel.updateLayout();
3391 alignPanel.paintAlignment(true, false);
3401 protected void scaleRight_actionPerformed(ActionEvent e)
3403 viewport.setScaleRightWrapped(scaleRight.isSelected());
3404 alignPanel.updateLayout();
3405 alignPanel.paintAlignment(true, false);
3415 public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3417 viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3418 alignPanel.paintAlignment(false, false);
3428 public void viewTextMenuItem_actionPerformed(ActionEvent e)
3430 viewport.setShowText(viewTextMenuItem.isSelected());
3431 alignPanel.paintAlignment(false, false);
3441 protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3443 viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3444 alignPanel.paintAlignment(false, false);
3447 public FeatureSettings featureSettings;
3450 public FeatureSettingsControllerI getFeatureSettingsUI()
3452 return featureSettings;
3456 public void featureSettings_actionPerformed(ActionEvent e)
3458 showFeatureSettingsUI();
3462 public FeatureSettingsControllerI showFeatureSettingsUI()
3464 if (featureSettings != null)
3466 featureSettings.closeOldSettings();
3467 featureSettings = null;
3469 if (!showSeqFeatures.isSelected())
3471 // make sure features are actually displayed
3472 showSeqFeatures.setSelected(true);
3473 showSeqFeatures_actionPerformed(null);
3475 featureSettings = new FeatureSettings(this);
3476 return featureSettings;
3480 * Set or clear 'Show Sequence Features'
3486 public void showSeqFeatures_actionPerformed(ActionEvent evt)
3488 viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3489 alignPanel.paintAlignment(true, true);
3493 * Action on toggle of the 'Show annotations' menu item. This shows or hides
3494 * the annotations panel as a whole.
3496 * The options to show/hide all annotations should be enabled when the panel
3497 * is shown, and disabled when the panel is hidden.
3502 public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3504 final boolean setVisible = annotationPanelMenuItem.isSelected();
3505 viewport.setShowAnnotation(setVisible);
3506 this.showAllSeqAnnotations.setEnabled(setVisible);
3507 this.hideAllSeqAnnotations.setEnabled(setVisible);
3508 this.showAllAlAnnotations.setEnabled(setVisible);
3509 this.hideAllAlAnnotations.setEnabled(setVisible);
3510 alignPanel.updateLayout();
3514 public void alignmentProperties()
3517 StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3520 String content = MessageManager.formatMessage("label.html_content",
3522 { contents.toString() });
3525 if (Platform.isJS())
3527 JLabel textLabel = new JLabel();
3528 textLabel.setText(content);
3529 textLabel.setBackground(Color.WHITE);
3531 pane = new JPanel(new BorderLayout());
3532 ((JPanel) pane).setOpaque(true);
3533 pane.setBackground(Color.WHITE);
3534 ((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3543 JEditorPane editPane = new JEditorPane("text/html", "");
3544 editPane.setEditable(false);
3545 editPane.setText(content);
3549 JInternalFrame frame = new JInternalFrame();
3550 frame.setFrameIcon(null);
3551 frame.getContentPane().add(new JScrollPane(pane));
3553 Desktop.addInternalFrame(frame, MessageManager
3554 .formatMessage("label.alignment_properties", new Object[]
3555 { getTitle() }), 500, 400);
3559 * Opens an Overview panel for the alignment, unless one is open already
3564 public void overviewMenuItem_actionPerformed(ActionEvent e)
3566 boolean showHiddenRegions = Cache
3567 .getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3568 openOverviewPanel(showHiddenRegions);
3571 public OverviewPanel openOverviewPanel(boolean showHidden)
3573 if (alignPanel.overviewPanel != null)
3575 return alignPanel.overviewPanel;
3577 JInternalFrame frame = new JInternalFrame();
3578 frame.setFrameIcon(null);
3579 final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3581 frame.setContentPane(overview);
3583 alignPanel.setOverviewPanel(overview);
3584 alignPanel.setOverviewTitle(this);
3586 Desktop.addInternalFrame(frame, overview.getTitle(), true,
3587 frame.getWidth(), frame.getHeight(), true, true);
3589 frame.setLayer(JLayeredPane.PALETTE_LAYER);
3590 final AlignmentPanel thePanel = this.alignPanel;
3591 frame.addInternalFrameListener(
3592 new javax.swing.event.InternalFrameAdapter()
3595 public void internalFrameClosed(
3596 javax.swing.event.InternalFrameEvent evt)
3599 thePanel.setOverviewPanel(null);
3602 if (getKeyListeners().length > 0)
3604 frame.addKeyListener(getKeyListeners()[0]);
3611 public void textColour_actionPerformed()
3613 new TextColourChooser().chooseColour(alignPanel, null);
3617 * public void covariationColour_actionPerformed() {
3619 * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3623 public void annotationColour_actionPerformed()
3625 new AnnotationColourChooser(viewport, alignPanel);
3629 public void annotationColumn_actionPerformed(ActionEvent e)
3631 new AnnotationColumnChooser(viewport, alignPanel);
3635 * Action on the user checking or unchecking the option to apply the selected
3636 * colour scheme to all groups. If unchecked, groups may have their own
3637 * independent colour schemes.
3642 public void applyToAllGroups_actionPerformed(boolean selected)
3644 viewport.setColourAppliesToAllGroups(selected);
3648 * Action on user selecting a colour from the colour menu
3651 * the name (not the menu item label!) of the colour scheme
3654 public void changeColour_actionPerformed(String name)
3657 * 'User Defined' opens a panel to configure or load a
3658 * user-defined colour scheme
3660 if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3662 new UserDefinedColours(alignPanel);
3667 * otherwise set the chosen colour scheme (or null for 'None')
3669 ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3670 viewport, viewport.getAlignment(),
3671 viewport.getHiddenRepSequences());
3676 * Actions on setting or changing the alignment colour scheme
3681 public void changeColour(ColourSchemeI cs)
3683 // TODO: pull up to controller method
3684 ColourMenuHelper.setColourSelected(colourMenu, cs);
3686 viewport.setGlobalColourScheme(cs);
3688 alignPanel.paintAlignment(true, true);
3692 * Show the PID threshold slider panel
3695 protected void modifyPID_actionPerformed()
3697 SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3698 alignPanel.getViewName());
3699 SliderPanel.showPIDSlider();
3703 * Show the Conservation slider panel
3706 protected void modifyConservation_actionPerformed()
3708 SliderPanel.setConservationSlider(alignPanel,
3709 viewport.getResidueShading(), alignPanel.getViewName());
3710 SliderPanel.showConservationSlider();
3714 * Action on selecting or deselecting (Colour) By Conservation
3717 public void conservationMenuItem_actionPerformed(boolean selected)
3719 modifyConservation.setEnabled(selected);
3720 viewport.setConservationSelected(selected);
3721 viewport.getResidueShading().setConservationApplied(selected);
3723 changeColour(viewport.getGlobalColourScheme());
3726 modifyConservation_actionPerformed();
3730 SliderPanel.hideConservationSlider();
3735 * Action on selecting or deselecting (Colour) Above PID Threshold
3738 public void abovePIDThreshold_actionPerformed(boolean selected)
3740 modifyPID.setEnabled(selected);
3741 viewport.setAbovePIDThreshold(selected);
3744 viewport.getResidueShading().setThreshold(0,
3745 viewport.isIgnoreGapsConsensus());
3748 changeColour(viewport.getGlobalColourScheme());
3751 modifyPID_actionPerformed();
3755 SliderPanel.hidePIDSlider();
3766 public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3768 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3769 AlignmentSorter.sortByPID(viewport.getAlignment(),
3770 viewport.getAlignment().getSequenceAt(0));
3771 addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3772 viewport.getAlignment()));
3773 alignPanel.paintAlignment(true, false);
3783 public void sortIDMenuItem_actionPerformed(ActionEvent e)
3785 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3786 AlignmentSorter.sortByID(viewport.getAlignment());
3788 new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3789 alignPanel.paintAlignment(true, false);
3799 public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3801 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3802 AlignmentSorter.sortByLength(viewport.getAlignment());
3803 addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3804 viewport.getAlignment()));
3805 alignPanel.paintAlignment(true, false);
3815 public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3817 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3818 AlignmentSorter.sortByGroup(viewport.getAlignment());
3819 addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3820 viewport.getAlignment()));
3822 alignPanel.paintAlignment(true, false);
3832 public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3834 new RedundancyPanel(alignPanel, this);
3844 public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3846 if ((viewport.getSelectionGroup() == null)
3847 || (viewport.getSelectionGroup().getSize() < 2))
3849 JvOptionPane.showInternalMessageDialog(this,
3850 MessageManager.getString(
3851 "label.you_must_select_least_two_sequences"),
3852 MessageManager.getString("label.invalid_selection"),
3853 JvOptionPane.WARNING_MESSAGE);
3857 JInternalFrame frame = new JInternalFrame();
3858 frame.setFrameIcon(null);
3859 frame.setContentPane(new PairwiseAlignPanel(viewport));
3860 Desktop.addInternalFrame(frame,
3861 MessageManager.getString("action.pairwise_alignment"), 600,
3867 public void autoCalculate_actionPerformed(ActionEvent e)
3869 viewport.autoCalculateConsensus = autoCalculate.isSelected();
3870 if (viewport.autoCalculateConsensus)
3872 viewport.firePropertyChange("alignment", null,
3873 viewport.getAlignment().getSequences());
3878 public void sortByTreeOption_actionPerformed(ActionEvent e)
3880 viewport.sortByTree = sortByTree.isSelected();
3884 protected void listenToViewSelections_actionPerformed(ActionEvent e)
3886 viewport.followSelection = listenToViewSelections.isSelected();
3890 * Constructs a tree panel and adds it to the desktop
3893 * tree type (NJ or AV)
3895 * name of score model used to compute the tree
3897 * parameters for the distance or similarity calculation
3899 void newTreePanel(String type, String modelName,
3900 SimilarityParamsI options)
3902 String frameTitle = "";
3905 boolean onSelection = false;
3906 if (viewport.getSelectionGroup() != null
3907 && viewport.getSelectionGroup().getSize() > 0)
3909 SequenceGroup sg = viewport.getSelectionGroup();
3911 /* Decide if the selection is a column region */
3912 for (SequenceI _s : sg.getSequences())
3914 if (_s.getLength() < sg.getEndRes())
3916 JvOptionPane.showMessageDialog(Desktop.desktop,
3917 MessageManager.getString(
3918 "label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
3919 MessageManager.getString(
3920 "label.sequences_selection_not_aligned"),
3921 JvOptionPane.WARNING_MESSAGE);
3930 if (viewport.getAlignment().getHeight() < 2)
3936 tp = new TreePanel(alignPanel, type, modelName, options);
3937 frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
3939 frameTitle += " from ";
3941 if (viewport.getViewName() != null)
3943 frameTitle += viewport.getViewName() + " of ";
3946 frameTitle += this.title;
3948 Desktop.addInternalFrame(tp, frameTitle, 600, 500);
3959 public void addSortByOrderMenuItem(String title,
3960 final AlignmentOrder order)
3962 final JMenuItem item = new JMenuItem(MessageManager
3963 .formatMessage("action.by_title_param", new Object[]
3966 item.addActionListener(new java.awt.event.ActionListener()
3969 public void actionPerformed(ActionEvent e)
3971 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3973 // TODO: JBPNote - have to map order entries to curent SequenceI
3975 AlignmentSorter.sortBy(viewport.getAlignment(), order);
3977 addHistoryItem(new OrderCommand(order.getName(), oldOrder,
3978 viewport.getAlignment()));
3980 alignPanel.paintAlignment(true, false);
3986 * Add a new sort by annotation score menu item
3989 * the menu to add the option to
3991 * the label used to retrieve scores for each sequence on the
3994 public void addSortByAnnotScoreMenuItem(JMenu sort,
3995 final String scoreLabel)
3997 final JMenuItem item = new JMenuItem(scoreLabel);
3999 item.addActionListener(new java.awt.event.ActionListener()
4002 public void actionPerformed(ActionEvent e)
4004 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4005 AlignmentSorter.sortByAnnotationScore(scoreLabel,
4006 viewport.getAlignment());// ,viewport.getSelectionGroup());
4007 addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
4008 viewport.getAlignment()));
4009 alignPanel.paintAlignment(true, false);
4015 * last hash for alignment's annotation array - used to minimise cost of
4018 protected int _annotationScoreVectorHash;
4021 * search the alignment and rebuild the sort by annotation score submenu the
4022 * last alignment annotation vector hash is stored to minimize cost of
4023 * rebuilding in subsequence calls.
4027 public void buildSortByAnnotationScoresMenu()
4029 if (viewport.getAlignment().getAlignmentAnnotation() == null)
4034 if (viewport.getAlignment().getAlignmentAnnotation()
4035 .hashCode() != _annotationScoreVectorHash)
4037 sortByAnnotScore.removeAll();
4038 // almost certainly a quicker way to do this - but we keep it simple
4039 Hashtable<String, String> scoreSorts = new Hashtable<>();
4040 AlignmentAnnotation aann[];
4041 for (SequenceI sqa : viewport.getAlignment().getSequences())
4043 aann = sqa.getAnnotation();
4044 for (int i = 0; aann != null && i < aann.length; i++)
4046 if (aann[i].hasScore() && aann[i].sequenceRef != null)
4048 scoreSorts.put(aann[i].label, aann[i].label);
4052 Enumeration<String> labels = scoreSorts.keys();
4053 while (labels.hasMoreElements())
4055 addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4057 sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4060 _annotationScoreVectorHash = viewport.getAlignment()
4061 .getAlignmentAnnotation().hashCode();
4066 * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4067 * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
4068 * call. Listeners are added to remove the menu item when the treePanel is
4069 * closed, and adjust the tree leaf to sequence mapping when the alignment is
4073 public void buildTreeSortMenu()
4075 sortByTreeMenu.removeAll();
4077 List<Component> comps = PaintRefresher.components
4078 .get(viewport.getSequenceSetId());
4079 List<TreePanel> treePanels = new ArrayList<>();
4080 for (Component comp : comps)
4082 if (comp instanceof TreePanel)
4084 treePanels.add((TreePanel) comp);
4088 if (treePanels.size() < 1)
4090 sortByTreeMenu.setVisible(false);
4094 sortByTreeMenu.setVisible(true);
4096 for (final TreePanel tp : treePanels)
4098 final JMenuItem item = new JMenuItem(tp.getTitle());
4099 item.addActionListener(new java.awt.event.ActionListener()
4102 public void actionPerformed(ActionEvent e)
4104 tp.sortByTree_actionPerformed();
4105 addHistoryItem(tp.sortAlignmentIn(alignPanel));
4110 sortByTreeMenu.add(item);
4114 public boolean sortBy(AlignmentOrder alorder, String undoname)
4116 SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4117 AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4118 if (undoname != null)
4120 addHistoryItem(new OrderCommand(undoname, oldOrder,
4121 viewport.getAlignment()));
4123 alignPanel.paintAlignment(true, false);
4128 * Work out whether the whole set of sequences or just the selected set will
4129 * be submitted for multiple alignment.
4132 public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4134 // Now, check we have enough sequences
4135 AlignmentView msa = null;
4137 if ((viewport.getSelectionGroup() != null)
4138 && (viewport.getSelectionGroup().getSize() > 1))
4140 // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4141 // some common interface!
4143 * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4144 * SequenceI[sz = seqs.getSize(false)];
4146 * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
4147 * seqs.getSequenceAt(i); }
4149 msa = viewport.getAlignmentView(true);
4151 else if (viewport.getSelectionGroup() != null
4152 && viewport.getSelectionGroup().getSize() == 1)
4154 int option = JvOptionPane.showConfirmDialog(this,
4155 MessageManager.getString("warn.oneseq_msainput_selection"),
4156 MessageManager.getString("label.invalid_selection"),
4157 JvOptionPane.OK_CANCEL_OPTION);
4158 if (option == JvOptionPane.OK_OPTION)
4160 msa = viewport.getAlignmentView(false);
4165 msa = viewport.getAlignmentView(false);
4171 * Decides what is submitted to a secondary structure prediction service: the
4172 * first sequence in the alignment, or in the current selection, or, if the
4173 * alignment is 'aligned' (ie padded with gaps), then the currently selected
4174 * region or the whole alignment. (where the first sequence in the set is the
4175 * one that the prediction will be for).
4177 public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4179 AlignmentView seqs = null;
4181 if ((viewport.getSelectionGroup() != null)
4182 && (viewport.getSelectionGroup().getSize() > 0))
4184 seqs = viewport.getAlignmentView(true);
4188 seqs = viewport.getAlignmentView(false);
4190 // limit sequences - JBPNote in future - could spawn multiple prediction
4192 // TODO: viewport.getAlignment().isAligned is a global state - the local
4193 // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4194 if (!viewport.getAlignment().isAligned(false))
4196 seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4197 // TODO: if seqs.getSequences().length>1 then should really have warned
4211 protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4213 // Pick the tree file
4214 JalviewFileChooser chooser = new JalviewFileChooser(
4215 Cache.getProperty("LAST_DIRECTORY"));
4216 chooser.setFileView(new JalviewFileView());
4217 chooser.setDialogTitle(
4218 MessageManager.getString("label.select_newick_like_tree_file"));
4219 chooser.setToolTipText(
4220 MessageManager.getString("label.load_tree_file"));
4222 chooser.setResponseHandler(0, () -> {
4223 String filePath = chooser.getSelectedFile().getPath();
4224 Cache.setProperty("LAST_DIRECTORY", filePath);
4225 NewickFile fin = null;
4228 fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4229 DataSourceType.FILE));
4230 viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4231 } catch (Exception ex)
4233 JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4234 MessageManager.getString("label.problem_reading_tree_file"),
4235 JvOptionPane.WARNING_MESSAGE);
4236 ex.printStackTrace();
4238 if (fin != null && fin.hasWarningMessage())
4240 JvOptionPane.showMessageDialog(Desktop.desktop,
4241 fin.getWarningMessage(),
4243 .getString("label.possible_problem_with_tree_file"),
4244 JvOptionPane.WARNING_MESSAGE);
4247 chooser.showOpenDialog(this);
4250 public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4252 return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4255 public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4256 int h, int x, int y)
4258 return showNewickTree(nf, treeTitle, null, w, h, x, y);
4262 * Add a treeviewer for the tree extracted from a Newick file object to the
4263 * current alignment view
4270 * Associated alignment input data (or null)
4279 * @return TreePanel handle
4281 public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4282 AlignmentView input, int w, int h, int x, int y)
4284 TreePanel tp = null;
4290 if (nf.getTree() != null)
4292 tp = new TreePanel(alignPanel, nf, treeTitle, input);
4298 tp.setLocation(x, y);
4301 Desktop.addInternalFrame(tp, treeTitle, w, h);
4303 } catch (Exception ex)
4305 ex.printStackTrace();
4311 public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4314 int w = 400, h = 500;
4318 NewickFile fin = new NewickFile(
4319 new FileParse(cm.getNewick(), DataSourceType.PASTE));
4320 String title = aa.label + " " + cm.getTreeMethod() + " tree"
4321 + (aa.sequenceRef != null
4322 ? (" for " + aa.sequenceRef.getDisplayId(false))
4325 showColumnWiseTree(fin, aa, title, w, h, x, y);
4326 } catch (Throwable xx)
4328 Console.error("Unexpected exception showing tree for contact matrix",
4333 public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4334 String treeTitle, int w, int h, int x, int y)
4339 if (nf.getTree() == null)
4343 TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4349 tp.setLocation(x, y);
4352 Desktop.addInternalFrame(tp, treeTitle, w, h);
4354 } catch (Throwable xx)
4356 Console.error("Unexpected exception showing tree for contact matrix",
4362 private boolean buildingMenu = false;
4365 * Generates menu items and listener event actions for web service clients
4368 public void BuildWebServiceMenu()
4370 while (buildingMenu)
4375 .errPrintln("Waiting for building menu to finish.");
4377 } catch (Exception e)
4381 final AlignFrame me = this;
4382 buildingMenu = true;
4383 new Thread(new Runnable()
4388 final List<JMenuItem> legacyItems = new ArrayList<>();
4391 // jalview.bin.Console.errPrintln("Building ws menu again "
4392 // + Thread.currentThread());
4393 // TODO: add support for context dependent disabling of services based
4395 // alignment and current selection
4396 // TODO: add additional serviceHandle parameter to specify abstract
4398 // class independently of AbstractName
4399 // TODO: add in rediscovery GUI function to restart discoverer
4400 // TODO: group services by location as well as function and/or
4402 // object broker mechanism.
4403 final Vector<JMenu> wsmenu = new Vector<>();
4404 final IProgressIndicator af = me;
4407 * do not i18n these strings - they are hard-coded in class
4408 * compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4409 * SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4411 final JMenu msawsmenu = new JMenu("Alignment");
4412 final JMenu secstrmenu = new JMenu(
4413 "Secondary Structure Prediction");
4414 final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4415 final JMenu analymenu = new JMenu("Analysis");
4416 final JMenu dismenu = new JMenu("Protein Disorder");
4417 // JAL-940 - only show secondary structure prediction services from
4418 // the legacy server
4419 if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4421 Discoverer.services != null && (Discoverer.services.size() > 0))
4423 // TODO: refactor to allow list of AbstractName/Handler bindings to
4425 // stored or retrieved from elsewhere
4426 // No MSAWS used any more:
4427 // Vector msaws = null; // (Vector)
4428 // Discoverer.services.get("MsaWS");
4429 Vector<ServiceHandle> secstrpr = Discoverer.services
4431 if (secstrpr != null)
4433 // Add any secondary structure prediction services
4434 for (int i = 0, j = secstrpr.size(); i < j; i++)
4436 final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4437 jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4438 .getServiceClient(sh);
4439 int p = secstrmenu.getItemCount();
4440 impl.attachWSMenuEntry(secstrmenu, me);
4441 int q = secstrmenu.getItemCount();
4442 for (int litm = p; litm < q; litm++)
4444 legacyItems.add(secstrmenu.getItem(litm));
4450 // Add all submenus in the order they should appear on the web
4452 wsmenu.add(msawsmenu);
4453 wsmenu.add(secstrmenu);
4454 wsmenu.add(dismenu);
4455 wsmenu.add(analymenu);
4456 // No search services yet
4457 // wsmenu.add(seqsrchmenu);
4459 javax.swing.SwingUtilities.invokeLater(new Runnable()
4466 webService.removeAll();
4467 // first, add discovered services onto the webservices menu
4468 if (wsmenu.size() > 0)
4470 for (int i = 0, j = wsmenu.size(); i < j; i++)
4472 webService.add(wsmenu.get(i));
4477 webService.add(me.webServiceNoServices);
4479 // TODO: move into separate menu builder class.
4481 // logic for 2.11.1.4 is
4482 // always look to see if there is a discover. if there isn't
4483 // we can't show any Jws2 services
4484 // if there are services available, show them - regardless of
4485 // the 'show JWS2 preference'
4486 // if the discoverer is running then say so
4487 // otherwise offer to trigger discovery if 'show JWS2' is not
4489 Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4490 if (jws2servs != null)
4492 if (jws2servs.hasServices())
4494 jws2servs.attachWSMenuEntry(webService, me);
4495 for (Jws2Instance sv : jws2servs.getServices())
4497 if (sv.description.toLowerCase(Locale.ROOT)
4500 for (JMenuItem jmi : legacyItems)
4502 jmi.setVisible(false);
4508 if (jws2servs.isRunning())
4510 JMenuItem tm = new JMenuItem(
4511 "Still discovering JABA Services");
4512 tm.setEnabled(false);
4515 else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4517 JMenuItem enableJws2 = new JMenuItem(
4518 "Discover Web Services");
4519 enableJws2.setToolTipText(
4520 "Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4521 enableJws2.setEnabled(true);
4522 enableJws2.addActionListener(new ActionListener()
4526 public void actionPerformed(ActionEvent e)
4528 // start service discoverer, but ignore preference
4529 Desktop.instance.startServiceDiscovery(false,
4533 webService.add(enableJws2);
4537 build_urlServiceMenu(me.webService);
4538 build_fetchdbmenu(webService);
4539 for (JMenu item : wsmenu)
4541 if (item.getItemCount() == 0)
4543 item.setEnabled(false);
4547 item.setEnabled(true);
4550 } catch (Exception e)
4553 "Exception during web service menu building process.",
4558 } catch (Exception e)
4561 buildingMenu = false;
4568 * construct any groupURL type service menu entries.
4572 protected void build_urlServiceMenu(JMenu webService)
4574 // TODO: remove this code when 2.7 is released
4575 // DEBUG - alignmentView
4577 * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
4578 * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
4580 * @Override public void actionPerformed(ActionEvent e) {
4581 * jalview.datamodel.AlignmentView
4582 * .testSelectionViews(af.viewport.getAlignment(),
4583 * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4585 * }); webService.add(testAlView);
4587 // TODO: refactor to RestClient discoverer and merge menu entries for
4588 // rest-style services with other types of analysis/calculation service
4589 // SHmmr test client - still being implemented.
4590 // DEBUG - alignmentView
4592 for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4595 client.attachWSMenuEntry(
4596 JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4602 * Searches the alignment sequences for xRefs and builds the Show
4603 * Cross-References menu (formerly called Show Products), with database
4604 * sources for which cross-references are found (protein sources for a
4605 * nucleotide alignment and vice versa)
4607 * @return true if Show Cross-references menu should be enabled
4609 public boolean canShowProducts()
4611 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4612 AlignmentI dataset = viewport.getAlignment().getDataset();
4614 showProducts.removeAll();
4615 final boolean dna = viewport.getAlignment().isNucleotide();
4617 if (seqs == null || seqs.length == 0)
4619 // nothing to see here.
4623 boolean showp = false;
4626 List<String> ptypes = new CrossRef(seqs, dataset)
4627 .findXrefSourcesForSequences(dna);
4629 for (final String source : ptypes)
4632 final AlignFrame af = this;
4633 JMenuItem xtype = new JMenuItem(source);
4634 xtype.addActionListener(new ActionListener()
4637 public void actionPerformed(ActionEvent e)
4639 showProductsFor(af.viewport.getSequenceSelection(), dna,
4643 showProducts.add(xtype);
4645 showProducts.setVisible(showp);
4646 showProducts.setEnabled(showp);
4647 } catch (Exception e)
4650 "canShowProducts threw an exception - please report to help@jalview.org",
4658 * Finds and displays cross-references for the selected sequences (protein
4659 * products for nucleotide sequences, dna coding sequences for peptides).
4662 * the sequences to show cross-references for
4664 * true if from a nucleotide alignment (so showing proteins)
4666 * the database to show cross-references for
4668 protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4669 final String source)
4671 new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4676 * Construct and display a new frame containing the translation of this
4677 * frame's DNA sequences to their aligned protein (amino acid) equivalents.
4680 public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4682 AlignmentI al = null;
4685 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4687 al = dna.translateCdna(codeTable);
4688 } catch (Exception ex)
4690 Console.error("Exception during translation. Please report this !",
4692 final String msg = MessageManager.getString(
4693 "label.error_when_translating_sequences_submit_bug_report");
4694 final String errorTitle = MessageManager
4695 .getString("label.implementation_error")
4696 + MessageManager.getString("label.translation_failed");
4697 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4698 JvOptionPane.ERROR_MESSAGE);
4701 if (al == null || al.getHeight() == 0)
4703 final String msg = MessageManager.getString(
4704 "label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4705 final String errorTitle = MessageManager
4706 .getString("label.translation_failed");
4707 JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4708 JvOptionPane.WARNING_MESSAGE);
4712 AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4713 af.setFileFormat(this.currentFileFormat);
4714 final String newTitle = MessageManager
4715 .formatMessage("label.translation_of_params", new Object[]
4716 { this.getTitle(), codeTable.getId() });
4717 af.setTitle(newTitle);
4718 if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4720 final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4721 viewport.openSplitFrame(af, new Alignment(seqs));
4725 Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4732 * Set the file format
4736 public void setFileFormat(FileFormatI format)
4738 this.currentFileFormat = format;
4742 * Try to load a features file onto the alignment.
4745 * contents or path to retrieve file or a File object
4747 * access mode of file (see jalview.io.AlignFile)
4748 * @return true if features file was parsed correctly.
4750 public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4753 return avc.parseFeaturesFile(file, sourceType,
4754 Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4759 public void refreshFeatureUI(boolean enableIfNecessary)
4761 // note - currently this is only still here rather than in the controller
4762 // because of the featureSettings hard reference that is yet to be
4764 if (enableIfNecessary)
4766 viewport.setShowSequenceFeatures(true);
4767 showSeqFeatures.setSelected(true);
4773 public void dragEnter(DropTargetDragEvent evt)
4778 public void dragExit(DropTargetEvent evt)
4783 public void dragOver(DropTargetDragEvent evt)
4788 public void dropActionChanged(DropTargetDragEvent evt)
4793 public void drop(DropTargetDropEvent evt)
4795 // JAL-1552 - acceptDrop required before getTransferable call for
4796 // Java's Transferable for native dnd
4797 evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
4798 Transferable t = evt.getTransferable();
4800 final AlignFrame thisaf = this;
4801 final List<Object> files = new ArrayList<>();
4802 List<DataSourceType> protocols = new ArrayList<>();
4806 Desktop.transferFromDropTarget(files, protocols, evt, t);
4807 } catch (Exception e)
4809 e.printStackTrace();
4813 new Thread(new Runnable()
4820 // check to see if any of these files have names matching sequences
4823 SequenceIdMatcher idm = new SequenceIdMatcher(
4824 viewport.getAlignment().getSequencesArray());
4826 * Object[] { String,SequenceI}
4828 ArrayList<Object[]> filesmatched = new ArrayList<>();
4829 ArrayList<Object[]> filesnotmatched = new ArrayList<>();
4830 for (int i = 0; i < files.size(); i++)
4833 Object file = files.get(i);
4834 String fileName = file.toString();
4836 DataSourceType protocol = (file instanceof File
4837 ? DataSourceType.FILE
4838 : FormatAdapter.checkProtocol(fileName));
4839 if (protocol == DataSourceType.FILE)
4842 if (file instanceof File)
4845 Platform.cacheFileData(fl);
4849 fl = new File(fileName);
4851 pdbfn = fl.getName();
4853 else if (protocol == DataSourceType.URL)
4855 URL url = new URL(fileName);
4856 pdbfn = url.getFile();
4858 if (pdbfn.length() > 0)
4860 // attempt to find a match in the alignment
4861 SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
4862 int l = 0, c = pdbfn.indexOf(".");
4863 while (mtch == null && c != -1)
4868 } while ((c = pdbfn.indexOf(".", l)) > l);
4871 pdbfn = pdbfn.substring(0, l);
4873 mtch = idm.findAllIdMatches(pdbfn);
4875 FileFormatI type = null;
4880 type = new IdentifyFile().identify(file, protocol);
4881 } catch (Exception ex)
4885 if (type != null && type.isStructureFile())
4887 filesmatched.add(new Object[] { file, protocol, mtch });
4891 // File wasn't named like one of the sequences or wasn't a PDB
4893 filesnotmatched.add(new Object[] { file, protocol, type });
4897 if (filesmatched.size() > 0)
4899 boolean autoAssociate = Cache
4900 .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
4903 String msg = MessageManager.formatMessage(
4904 "label.automatically_associate_structure_files_with_sequences_same_name",
4906 { Integer.valueOf(filesmatched.size())
4908 String ttl = MessageManager.getString(
4909 "label.automatically_associate_structure_files_by_name");
4910 int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
4911 ttl, JvOptionPane.YES_NO_OPTION);
4912 autoAssociate = choice == JvOptionPane.YES_OPTION;
4916 for (Object[] fm : filesmatched)
4918 // try and associate
4919 // TODO: may want to set a standard ID naming formalism for
4920 // associating PDB files which have no IDs.
4921 for (SequenceI toassoc : (SequenceI[]) fm[2])
4923 PDBEntry pe = new AssociatePdbFileWithSeq()
4924 .associatePdbWithSeq(fm[0].toString(),
4925 (DataSourceType) fm[1], toassoc, false,
4929 jalview.bin.Console.errPrintln("Associated file : "
4930 + (fm[0].toString()) + " with "
4931 + toassoc.getDisplayId(true));
4935 // TODO: do we need to update overview ? only if features are
4937 alignPanel.paintAlignment(true, false);
4943 * add declined structures as sequences
4945 for (Object[] o : filesmatched)
4947 filesnotmatched.add(new Object[] { o[0], o[1] });
4951 if (filesnotmatched.size() > 0)
4953 if (assocfiles > 0 && (Cache.getDefault(
4954 "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
4955 || JvOptionPane.showConfirmDialog(thisaf,
4956 "<html>" + MessageManager.formatMessage(
4957 "label.ignore_unmatched_dropped_files_info",
4960 filesnotmatched.size())
4963 MessageManager.getString(
4964 "label.ignore_unmatched_dropped_files"),
4965 JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
4969 for (Object[] fn : filesnotmatched)
4971 loadJalviewDataFile(fn[0], (DataSourceType) fn[1],
4972 (FileFormatI) fn[2], null);
4976 } catch (Exception ex)
4978 ex.printStackTrace();
4986 * Attempt to load a "dropped" file or URL string, by testing in turn for
4988 * <li>an Annotation file</li>
4989 * <li>a JNet file</li>
4990 * <li>a features file</li>
4991 * <li>else try to interpret as an alignment file</li>
4995 * either a filename or a URL string.
4997 public void loadJalviewDataFile(Object file, DataSourceType sourceType,
4998 FileFormatI format, SequenceI assocSeq)
5000 // BH 2018 was String file
5003 if (sourceType == null)
5005 sourceType = FormatAdapter.checkProtocol(file);
5007 // if the file isn't identified, or not positively identified as some
5008 // other filetype (PFAM is default unidentified alignment file type) then
5009 // try to parse as annotation.
5010 boolean isAnnotation = (format == null
5011 || FileFormat.Pfam.equals(format))
5012 ? new AnnotationFile().annotateAlignmentView(viewport,
5018 // first see if its a T-COFFEE score file
5019 TCoffeeScoreFile tcf = null;
5022 tcf = new TCoffeeScoreFile(file, sourceType);
5025 if (tcf.annotateAlignment(viewport.getAlignment(), true))
5029 new TCoffeeColourScheme(viewport.getAlignment()));
5030 isAnnotation = true;
5031 setStatus(MessageManager.getString(
5032 "label.successfully_pasted_tcoffee_scores_to_alignment"));
5036 // some problem - if no warning its probable that the ID matching
5037 // process didn't work
5038 JvOptionPane.showMessageDialog(Desktop.desktop,
5039 tcf.getWarningMessage() == null
5040 ? MessageManager.getString(
5041 "label.check_file_matches_sequence_ids_alignment")
5042 : tcf.getWarningMessage(),
5043 MessageManager.getString(
5044 "label.problem_reading_tcoffee_score_file"),
5045 JvOptionPane.WARNING_MESSAGE);
5052 } catch (Exception x)
5055 "Exception when processing data source as T-COFFEE score file",
5061 // try to see if its a JNet 'concise' style annotation file *before*
5063 // try to parse it as a features file
5066 format = new IdentifyFile().identify(file, sourceType);
5068 if (FileFormat.FeatureSettings == format)
5070 if (featureSettings != null)
5072 featureSettings.load(file, sourceType);
5076 FeatureSettings.loadFeatureSettingsFile(getFeatureRenderer(),
5077 fileObject, sourceType);
5080 else if (FileFormat.ScoreMatrix == format)
5082 ScoreMatrixFile sm = new ScoreMatrixFile(
5083 new FileParse(file, sourceType));
5085 // todo: i18n this message
5086 setStatus(MessageManager.formatMessage(
5087 "label.successfully_loaded_matrix",
5088 sm.getMatrixName()));
5090 else if (FileFormat.Jnet.equals(format))
5092 JPredFile predictions = new JPredFile(file, sourceType);
5093 new JnetAnnotationMaker();
5094 JnetAnnotationMaker.add_annotation(predictions,
5095 viewport.getAlignment(), 0, false);
5096 viewport.getAlignment().setupJPredAlignment();
5097 isAnnotation = true;
5099 // else if (IdentifyFile.FeaturesFile.equals(format))
5100 else if (FileFormat.Features.equals(format))
5102 if (parseFeaturesFile(file, sourceType))
5104 SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5105 if (splitFrame != null)
5107 splitFrame.repaint();
5111 alignPanel.paintAlignment(true, true);
5117 new FileLoader().LoadFile(viewport, file, sourceType, format);
5124 alignPanel.adjustAnnotationHeight();
5125 viewport.updateSequenceIdColours();
5126 buildSortByAnnotationScoresMenu();
5127 alignPanel.paintAlignment(true, true);
5129 } catch (Exception ex)
5131 ex.printStackTrace();
5132 } catch (OutOfMemoryError oom)
5137 } catch (Exception x)
5142 + (sourceType != null
5143 ? (sourceType == DataSourceType.PASTE
5145 : "using " + sourceType + " from "
5149 ? "(parsing as '" + format + "' file)"
5151 oom, Desktop.desktop);
5156 * Method invoked by the ChangeListener on the tabbed pane, in other words
5157 * when a different tabbed pane is selected by the user or programmatically.
5160 public void tabSelectionChanged(int index)
5165 * update current Overview window title (if there is one)
5166 * to add view name "Original" if necessary
5168 alignPanel.setOverviewTitle(this);
5171 * switch panels and set Overview title (if there is one
5172 * because it was opened automatically)
5174 alignPanel = alignPanels.get(index);
5175 alignPanel.setOverviewTitle(this);
5177 viewport = alignPanel.av;
5178 avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5179 setMenusFromViewport(viewport);
5180 if (featureSettings != null && featureSettings.isOpen()
5181 && featureSettings.fr.getViewport() != viewport)
5183 if (viewport.isShowSequenceFeatures())
5185 // refresh the featureSettings to reflect UI change
5186 showFeatureSettingsUI();
5190 // close feature settings for this view.
5191 featureSettings.close();
5198 * 'focus' any colour slider that is open to the selected viewport
5200 if (viewport.getConservationSelected())
5202 SliderPanel.setConservationSlider(alignPanel,
5203 viewport.getResidueShading(), alignPanel.getViewName());
5207 SliderPanel.hideConservationSlider();
5209 if (viewport.getAbovePIDThreshold())
5211 SliderPanel.setPIDSliderSource(alignPanel,
5212 viewport.getResidueShading(), alignPanel.getViewName());
5216 SliderPanel.hidePIDSlider();
5220 * If there is a frame linked to this one in a SplitPane, switch it to the
5221 * same view tab index. No infinite recursion of calls should happen, since
5222 * tabSelectionChanged() should not get invoked on setting the selected
5223 * index to an unchanged value. Guard against setting an invalid index
5224 * before the new view peer tab has been created.
5226 final AlignViewportI peer = viewport.getCodingComplement();
5229 AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5230 .getAlignPanel().alignFrame;
5231 if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5233 linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5239 * On right mouse click on view tab, prompt for and set new view name.
5242 public void tabbedPane_mousePressed(MouseEvent e)
5244 if (e.isPopupTrigger())
5246 String msg = MessageManager.getString("label.enter_view_name");
5247 String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5248 String reply = JvOptionPane.showInputDialog(msg, ttl);
5252 viewport.setViewName(reply);
5253 // TODO warn if reply is in getExistingViewNames()?
5254 tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5259 public AlignViewport getCurrentView()
5265 * Open the dialog for regex description parsing.
5268 protected void extractScores_actionPerformed(ActionEvent e)
5270 ParseProperties pp = new jalview.analysis.ParseProperties(
5271 viewport.getAlignment());
5272 // TODO: verify regex and introduce GUI dialog for version 2.5
5273 // if (pp.getScoresFromDescription("col", "score column ",
5274 // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5276 if (pp.getScoresFromDescription("description column",
5277 "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5279 buildSortByAnnotationScoresMenu();
5287 * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
5291 protected void showDbRefs_actionPerformed(ActionEvent e)
5293 viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5299 * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5303 protected void showNpFeats_actionPerformed(ActionEvent e)
5305 viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5309 * find the viewport amongst the tabs in this alignment frame and close that
5314 public boolean closeView(AlignViewportI av)
5318 this.closeMenuItem_actionPerformed(false);
5321 Component[] comp = tabbedPane.getComponents();
5322 for (int i = 0; comp != null && i < comp.length; i++)
5324 if (comp[i] instanceof AlignmentPanel)
5326 if (((AlignmentPanel) comp[i]).av == av)
5329 closeView((AlignmentPanel) comp[i]);
5337 protected void build_fetchdbmenu(JMenu webService)
5339 // Temporary hack - DBRef Fetcher always top level ws entry.
5340 // TODO We probably want to store a sequence database checklist in
5341 // preferences and have checkboxes.. rather than individual sources selected
5343 final JMenu rfetch = new JMenu(
5344 MessageManager.getString("action.fetch_db_references"));
5345 rfetch.setToolTipText(MessageManager.getString(
5346 "label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5347 webService.add(rfetch);
5349 final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5350 MessageManager.getString("option.trim_retrieved_seqs"));
5351 trimrs.setToolTipText(
5352 MessageManager.getString("label.trim_retrieved_sequences"));
5354 Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5355 trimrs.addActionListener(new ActionListener()
5358 public void actionPerformed(ActionEvent e)
5360 trimrs.setSelected(trimrs.isSelected());
5361 Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5362 Boolean.valueOf(trimrs.isSelected()).toString());
5366 JMenuItem fetchr = new JMenuItem(
5367 MessageManager.getString("label.standard_databases"));
5368 fetchr.setToolTipText(
5369 MessageManager.getString("label.fetch_embl_uniprot"));
5370 fetchr.addActionListener(new ActionListener()
5374 public void actionPerformed(ActionEvent e)
5376 new Thread(new Runnable()
5381 boolean isNucleotide = alignPanel.alignFrame.getViewport()
5382 .getAlignment().isNucleotide();
5383 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5384 alignPanel.av.getSequenceSelection(),
5385 alignPanel.alignFrame, null,
5386 alignPanel.alignFrame.featureSettings, isNucleotide);
5387 dbRefFetcher.addListener(new FetchFinishedListenerI()
5390 public void finished()
5393 for (FeatureSettingsModelI srcSettings : dbRefFetcher
5394 .getFeatureSettingsModels())
5397 alignPanel.av.mergeFeaturesStyle(srcSettings);
5399 AlignFrame.this.setMenusForViewport();
5402 dbRefFetcher.fetchDBRefs(false);
5410 new Thread(new Runnable()
5415 final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5416 .getSequenceFetcherSingleton();
5417 javax.swing.SwingUtilities.invokeLater(new Runnable()
5422 String[] dbclasses = sf.getNonAlignmentSources();
5423 List<DbSourceProxy> otherdb;
5424 JMenu dfetch = new JMenu();
5425 JMenu ifetch = new JMenu();
5426 JMenuItem fetchr = null;
5427 int comp = 0, icomp = 0, mcomp = 15;
5428 String mname = null;
5430 for (String dbclass : dbclasses)
5432 otherdb = sf.getSourceProxy(dbclass);
5433 // add a single entry for this class, or submenu allowing 'fetch
5435 if (otherdb == null || otherdb.size() < 1)
5441 mname = "From " + dbclass;
5443 if (otherdb.size() == 1)
5445 final DbSourceProxy[] dassource = otherdb
5446 .toArray(new DbSourceProxy[0]);
5447 DbSourceProxy src = otherdb.get(0);
5448 fetchr = new JMenuItem(src.getDbSource());
5449 fetchr.addActionListener(new ActionListener()
5453 public void actionPerformed(ActionEvent e)
5455 new Thread(new Runnable()
5461 boolean isNucleotide = alignPanel.alignFrame
5462 .getViewport().getAlignment()
5464 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5465 alignPanel.av.getSequenceSelection(),
5466 alignPanel.alignFrame, dassource,
5467 alignPanel.alignFrame.featureSettings,
5470 .addListener(new FetchFinishedListenerI()
5473 public void finished()
5475 FeatureSettingsModelI srcSettings = dassource[0]
5476 .getFeatureColourScheme();
5477 alignPanel.av.mergeFeaturesStyle(
5479 AlignFrame.this.setMenusForViewport();
5482 dbRefFetcher.fetchDBRefs(false);
5488 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5489 MessageManager.formatMessage(
5490 "label.fetch_retrieve_from", new Object[]
5491 { src.getDbName() })));
5497 final DbSourceProxy[] dassource = otherdb
5498 .toArray(new DbSourceProxy[0]);
5500 DbSourceProxy src = otherdb.get(0);
5501 fetchr = new JMenuItem(MessageManager
5502 .formatMessage("label.fetch_all_param", new Object[]
5503 { src.getDbSource() }));
5504 fetchr.addActionListener(new ActionListener()
5507 public void actionPerformed(ActionEvent e)
5509 new Thread(new Runnable()
5515 boolean isNucleotide = alignPanel.alignFrame
5516 .getViewport().getAlignment()
5518 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5519 alignPanel.av.getSequenceSelection(),
5520 alignPanel.alignFrame, dassource,
5521 alignPanel.alignFrame.featureSettings,
5524 .addListener(new FetchFinishedListenerI()
5527 public void finished()
5529 AlignFrame.this.setMenusForViewport();
5532 dbRefFetcher.fetchDBRefs(false);
5538 fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5539 MessageManager.formatMessage(
5540 "label.fetch_retrieve_from_all_sources",
5542 { Integer.valueOf(otherdb.size())
5544 src.getDbSource(), src.getDbName() })));
5547 // and then build the rest of the individual menus
5548 ifetch = new JMenu(MessageManager.formatMessage(
5549 "label.source_from_db_source", new Object[]
5550 { src.getDbSource() }));
5552 String imname = null;
5554 for (DbSourceProxy sproxy : otherdb)
5556 String dbname = sproxy.getDbName();
5557 String sname = dbname.length() > 5
5558 ? dbname.substring(0, 5) + "..."
5560 String msname = dbname.length() > 10
5561 ? dbname.substring(0, 10) + "..."
5565 imname = MessageManager
5566 .formatMessage("label.from_msname", new Object[]
5569 fetchr = new JMenuItem(msname);
5570 final DbSourceProxy[] dassrc = { sproxy };
5571 fetchr.addActionListener(new ActionListener()
5575 public void actionPerformed(ActionEvent e)
5577 new Thread(new Runnable()
5583 boolean isNucleotide = alignPanel.alignFrame
5584 .getViewport().getAlignment()
5586 DBRefFetcher dbRefFetcher = new DBRefFetcher(
5587 alignPanel.av.getSequenceSelection(),
5588 alignPanel.alignFrame, dassrc,
5589 alignPanel.alignFrame.featureSettings,
5592 .addListener(new FetchFinishedListenerI()
5595 public void finished()
5597 AlignFrame.this.setMenusForViewport();
5600 dbRefFetcher.fetchDBRefs(false);
5606 fetchr.setToolTipText(
5607 "<html>" + MessageManager.formatMessage(
5608 "label.fetch_retrieve_from", new Object[]
5612 if (++icomp >= mcomp || i == (otherdb.size()))
5614 ifetch.setText(MessageManager.formatMessage(
5615 "label.source_to_target", imname, sname));
5617 ifetch = new JMenu();
5625 if (comp >= mcomp || dbi >= (dbclasses.length))
5627 dfetch.setText(MessageManager.formatMessage(
5628 "label.source_to_target", mname, dbclass));
5630 dfetch = new JMenu();
5643 * Left justify the whole alignment.
5646 protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5648 AlignmentI al = viewport.getAlignment();
5650 viewport.firePropertyChange("alignment", null, al);
5654 * Right justify the whole alignment.
5657 protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5659 AlignmentI al = viewport.getAlignment();
5661 viewport.firePropertyChange("alignment", null, al);
5665 public void setShowSeqFeatures(boolean b)
5667 showSeqFeatures.setSelected(b);
5668 viewport.setShowSequenceFeatures(b);
5675 * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5676 * awt.event.ActionEvent)
5679 protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5681 viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5682 alignPanel.paintAlignment(false, false);
5686 protected void updateShowSSRadioButtons(JMenu showSS, ButtonGroup ssButtonGroup){
5688 List<String> ssSources = new ArrayList<String>();
5689 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5690 .getAlignmentAnnotation();
5692 ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(anns);
5694 // Get the currently selected radio button
5695 String selectedButtonModelName = getSelectedRadioButtonDisplayString(ssButtonGroup);
5696 boolean selectedButtonModel = false;
5698 // Clear existing radio buttons
5700 JRadioButtonMenuItem radioButtonAllSS = new JRadioButtonMenuItem("All");
5701 radioButtonAllSS.addActionListener(new ActionListener() {
5703 public void actionPerformed(ActionEvent e) {
5704 showSS_actionPerformed("All");
5707 ssButtonGroup.add(radioButtonAllSS);
5708 showSS.add(radioButtonAllSS);
5710 JRadioButtonMenuItem radioButtonNoneSS = new JRadioButtonMenuItem("None");
5711 radioButtonNoneSS.addActionListener(new ActionListener() {
5713 public void actionPerformed(ActionEvent e) {
5714 showSS_actionPerformed("None");
5717 ssButtonGroup.add(radioButtonNoneSS);
5718 showSS.add(radioButtonNoneSS);
5719 showSS.addSeparator();
5721 for(String ssSource : ssSources) {
5723 JRadioButtonMenuItem radioButton = new JRadioButtonMenuItem(ssSource);
5724 radioButton.addActionListener(new ActionListener() {
5726 public void actionPerformed(ActionEvent e) {
5727 showSS_actionPerformed(ssSource);
5730 ssButtonGroup.add(radioButton);
5731 showSS.add(radioButton);
5733 // Check if this radio button's name matches the selected radio button's name
5734 if (ssSource.equals(selectedButtonModelName)) {
5735 radioButton.setSelected(true); // Select this radio button
5736 selectedButtonModel = true;
5741 if (selectedButtonModelName == "None") {
5742 // If no radio button was previously selected, select "All"
5743 ssButtonGroup.setSelected(radioButtonNoneSS.getModel(), true);
5744 selectedButtonModel = true;
5746 if (!selectedButtonModel) {
5747 // If no radio button was previously selected, select "All"
5748 ssButtonGroup.setSelected(radioButtonAllSS.getModel(), true);
5753 protected void showSS_actionPerformed(String ssSourceSelection){
5756 AlignmentAnnotation[] annotations = alignPanel.getAlignment()
5757 .getAlignmentAnnotation();
5759 for (AlignmentAnnotation aa: annotations) {
5761 for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
5763 if (label.equals(aa.label)) {
5767 if(ssSourceSelection == "All") {
5772 String ssSource = AlignmentUtils.extractSSSourceFromAnnotationDescription(aa);
5773 if(ssSource.equals(ssSourceSelection)) {
5785 List<AlignCalcWorkerI> workers = viewport.getCalcManager()
5786 .getRegisteredWorkersOfClass(SecondaryStructureConsensusThread.class);
5787 if (!workers.isEmpty()) {
5789 viewport.getCalcManager().startWorker(workers.remove(0));
5793 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5794 alignPanel.updateAnnotation();
5795 alignPanel.paintAlignment(true, true);
5801 protected String getSelectedRadioButtonDisplayString(ButtonGroup ssButtonGroup) {
5802 Enumeration<AbstractButton> buttons = ssButtonGroup.getElements();
5803 while (buttons.hasMoreElements()) {
5804 AbstractButton button = buttons.nextElement();
5805 if (button.isSelected()) {
5806 return button.getText();
5809 return null; // No radio button is selected
5816 * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
5820 protected void showGroupConsensus_actionPerformed(ActionEvent e)
5822 viewport.setShowGroupConsensus(showGroupConsensus.getState());
5823 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5831 * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
5832 * .event.ActionEvent)
5835 protected void showGroupConservation_actionPerformed(ActionEvent e)
5837 viewport.setShowGroupConservation(showGroupConservation.getState());
5838 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5845 * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
5846 * .event.ActionEvent)
5849 protected void showConsensusHistogram_actionPerformed(ActionEvent e)
5851 viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
5852 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5856 protected void showSSConsensusHistogram_actionPerformed(ActionEvent e)
5858 viewport.setShowSSConsensusHistogram(showSSConsensusHistogram.getState());
5859 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5866 * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
5867 * .event.ActionEvent)
5870 protected void showSequenceLogo_actionPerformed(ActionEvent e)
5872 viewport.setShowSequenceLogo(showSequenceLogo.getState());
5873 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5877 protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
5879 showSequenceLogo.setState(true);
5880 viewport.setShowSequenceLogo(true);
5881 viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
5882 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5886 protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
5888 alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
5895 * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
5896 * .event.ActionEvent)
5899 protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
5901 if (avc.makeGroupsFromSelection())
5903 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5904 alignPanel.updateAnnotation();
5905 alignPanel.paintAlignment(true,
5906 viewport.needToUpdateStructureViews());
5910 public void clearAlignmentSeqRep()
5912 // TODO refactor alignmentseqrep to controller
5913 if (viewport.getAlignment().hasSeqrep())
5915 viewport.getAlignment().setSeqrep(null);
5916 PaintRefresher.Refresh(this, viewport.getSequenceSetId());
5917 alignPanel.updateAnnotation();
5918 alignPanel.paintAlignment(true, true);
5923 protected void createGroup_actionPerformed(ActionEvent e)
5925 if (avc.createGroup())
5927 if (applyAutoAnnotationSettings.isSelected())
5929 alignPanel.updateAnnotation(true, false);
5931 alignPanel.alignmentChanged();
5936 protected void unGroup_actionPerformed(ActionEvent e)
5940 alignPanel.alignmentChanged();
5945 * make the given alignmentPanel the currently selected tab
5947 * @param alignmentPanel
5949 public void setDisplayedView(AlignmentPanel alignmentPanel)
5951 if (!viewport.getSequenceSetId()
5952 .equals(alignmentPanel.av.getSequenceSetId()))
5954 throw new Error(MessageManager.getString(
5955 "error.implementation_error_cannot_show_view_alignment_frame"));
5957 if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
5958 .indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
5960 tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
5965 * Action on selection of menu options to Show or Hide annotations.
5968 * @param forSequences
5969 * update sequence-related annotations
5970 * @param forAlignment
5971 * update non-sequence-related annotations
5974 public void setAnnotationsVisibility(boolean visible,
5975 boolean forSequences, boolean forAlignment)
5977 AlignmentAnnotation[] anns = alignPanel.getAlignment()
5978 .getAlignmentAnnotation();
5983 for (AlignmentAnnotation aa : anns)
5986 * don't display non-positional annotations on an alignment
5988 if (aa.annotations == null)
5992 boolean apply = (aa.sequenceRef == null && forAlignment)
5993 || (aa.sequenceRef != null && forSequences);
5996 aa.visible = visible;
5999 alignPanel.validateAnnotationDimensions(true);
6000 // TODO this triggers relayout of annotation panel - otherwise annotation
6001 // label height is different to panel height
6002 alignPanel.fontChanged();
6003 alignPanel.alignmentChanged();
6007 * Store selected annotation sort order for the view and repaint.
6010 protected void sortAnnotations_actionPerformed()
6012 this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
6014 .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
6015 alignPanel.paintAlignment(false, false);
6020 * @return alignment panels in this alignment frame
6022 public List<? extends AlignmentViewPanel> getAlignPanels()
6024 // alignPanels is never null
6025 // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
6030 * Open a new alignment window, with the cDNA associated with this (protein)
6031 * alignment, aligned as is the protein.
6033 protected void viewAsCdna_actionPerformed()
6035 // TODO no longer a menu action - refactor as required
6036 final AlignmentI alignment = getViewport().getAlignment();
6037 List<AlignedCodonFrame> mappings = alignment.getCodonFrames();
6038 if (mappings == null)
6042 List<SequenceI> cdnaSeqs = new ArrayList<>();
6043 for (SequenceI aaSeq : alignment.getSequences())
6045 for (AlignedCodonFrame acf : mappings)
6047 SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
6051 * There is a cDNA mapping for this protein sequence - add to new
6052 * alignment. It will share the same dataset sequence as other mapped
6053 * cDNA (no new mappings need to be created).
6055 final Sequence newSeq = new Sequence(dnaSeq);
6056 newSeq.setDatasetSequence(dnaSeq);
6057 cdnaSeqs.add(newSeq);
6061 if (cdnaSeqs.size() == 0)
6063 // show a warning dialog no mapped cDNA
6066 AlignmentI cdna = new Alignment(
6067 cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
6068 GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
6069 AlignFrame.DEFAULT_HEIGHT);
6070 cdna.alignAs(alignment);
6071 String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
6073 Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
6074 AlignFrame.DEFAULT_HEIGHT);
6078 * Set visibility of dna/protein complement view (available when shown in a
6084 protected void showComplement_actionPerformed(boolean show)
6086 SplitContainerI sf = getSplitViewContainer();
6089 sf.setComplementVisible(this, show);
6094 * Generate the reverse (optionally complemented) of the selected sequences,
6095 * and add them to the alignment
6098 protected void showReverse_actionPerformed(boolean complement)
6100 AlignmentI al = null;
6103 Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
6104 al = dna.reverseCdna(complement);
6105 viewport.addAlignment(al, "");
6106 addHistoryItem(new EditCommand(
6107 MessageManager.getString("label.add_sequences"), Action.PASTE,
6108 al.getSequencesArray(), 0, al.getWidth(),
6109 viewport.getAlignment()));
6110 } catch (Exception ex)
6112 jalview.bin.Console.errPrintln(ex.getMessage());
6118 * Try to run a script in the Groovy console, having first ensured that this
6119 * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
6120 * be targeted at this alignment.
6123 protected void runGroovy_actionPerformed()
6125 Jalview.getInstance().setCurrentAlignFrame(this);
6126 groovy.console.ui.Console console = Desktop.getGroovyConsole();
6127 if (console != null)
6131 console.setVariable(JalviewObjectI.currentAlFrameName, this);
6132 console.runScript();
6133 } catch (Exception ex)
6135 jalview.bin.Console.errPrintln((ex.toString()));
6136 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
6137 MessageManager.getString("label.couldnt_run_groovy_script"),
6138 MessageManager.getString("label.groovy_support_failed"),
6139 JvOptionPane.ERROR_MESSAGE);
6145 .errPrintln("Can't run Groovy script as console not found");
6150 * Hides columns containing (or not containing) a specified feature, provided
6151 * that would not leave all columns hidden
6153 * @param featureType
6154 * @param columnsContaining
6157 public boolean hideFeatureColumns(String featureType,
6158 boolean columnsContaining)
6160 boolean notForHiding = avc.markColumnsContainingFeatures(
6161 columnsContaining, false, false, featureType);
6164 if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6165 false, featureType))
6167 getViewport().hideSelectedColumns();
6175 protected void selectHighlightedColumns_actionPerformed(
6176 ActionEvent actionEvent)
6178 // include key modifier check in case user selects from menu
6179 avc.markHighlightedColumns(
6180 (actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6181 (actionEvent.getModifiers() & (ActionEvent.META_MASK
6182 | ActionEvent.CTRL_MASK)) != 0);
6186 protected void copyHighlightedColumns_actionPerformed(
6187 ActionEvent actionEvent)
6189 avc.copyHighlightedRegionsToClipboard();
6193 * Rebuilds the Colour menu, including any user-defined colours which have
6194 * been loaded either on startup or during the session
6196 public void buildColourMenu()
6198 colourMenu.removeAll();
6200 colourMenu.add(applyToAllGroups);
6201 colourMenu.add(textColour);
6202 colourMenu.addSeparator();
6204 ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6205 viewport.getAlignment(), false);
6207 colourMenu.add(annotationColour);
6208 bg.add(annotationColour);
6209 colourMenu.addSeparator();
6210 colourMenu.add(conservationMenuItem);
6211 colourMenu.add(modifyConservation);
6212 colourMenu.add(abovePIDThreshold);
6213 colourMenu.add(modifyPID);
6215 ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6216 ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6220 * Open a dialog (if not already open) that allows the user to select and
6221 * calculate PCA or Tree analysis
6223 protected void openTreePcaDialog()
6225 if (alignPanel.getCalculationDialog() == null)
6227 new CalculationChooser(AlignFrame.this);
6232 protected void loadVcf_actionPerformed()
6234 JalviewFileChooser chooser = new JalviewFileChooser(
6235 Cache.getProperty("LAST_DIRECTORY"));
6236 chooser.setFileView(new JalviewFileView());
6237 chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6238 chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6239 final AlignFrame us = this;
6240 chooser.setResponseHandler(0, () -> {
6241 String choice = chooser.getSelectedFile().getPath();
6242 Cache.setProperty("LAST_DIRECTORY", choice);
6243 SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6244 new VCFLoader(choice).loadVCF(seqs, us);
6246 chooser.showOpenDialog(null);
6250 private Rectangle lastFeatureSettingsBounds = null;
6253 public void setFeatureSettingsGeometry(Rectangle bounds)
6255 lastFeatureSettingsBounds = bounds;
6259 public Rectangle getFeatureSettingsGeometry()
6261 return lastFeatureSettingsBounds;
6266 class PrintThread extends Thread
6270 public PrintThread(AlignmentPanel ap)
6275 static PageFormat pf;
6280 PrinterJob printJob = PrinterJob.getPrinterJob();
6284 printJob.setPrintable(ap, pf);
6288 printJob.setPrintable(ap);
6291 if (printJob.printDialog())
6296 } catch (Exception PrintException)
6298 PrintException.printStackTrace();