X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAlignViewport.java;h=9aac56da14e7742c5e50bed5f60c3461974df9c2;hb=6200addf078b7f7ace90597dc056dafc7fc602c1;hp=1a328f9a936cd4b85cdb7928fa21195ca10aff54;hpb=227ee1c1c69c228b67d408a0a83ae51bf5811272;p=jalview.git diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java index 1a328f9..954cfcc 100644 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@ -1,6 +1,6 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * @@ -18,53 +18,51 @@ * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ -/* - * Jalview - A Sequence Alignment Editor and Viewer - * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ package jalview.gui; -import jalview.analysis.NJTree; +import jalview.analysis.AlignmentUtils; +import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; import jalview.api.AlignViewportI; +import jalview.api.AlignmentViewPanel; +import jalview.api.FeatureColourI; +import jalview.api.FeatureSettingsModelI; +import jalview.api.FeaturesDisplayedI; +import jalview.api.ViewStyleI; import jalview.bin.Cache; -import jalview.datamodel.AlignmentAnnotation; +import jalview.commands.CommandI; +import jalview.datamodel.AlignedCodonFrame; +import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; -import jalview.datamodel.Annotation; import jalview.datamodel.ColumnSelection; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.Sequence; +import jalview.datamodel.HiddenColumns; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SearchResultsI; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.renderer.ResidueShader; +import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemeProperty; +import jalview.schemes.ResidueColourScheme; import jalview.schemes.UserColourScheme; import jalview.structure.SelectionSource; import jalview.structure.StructureSelectionManager; import jalview.structure.VamsasSource; +import jalview.util.ColorUtils; +import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; import jalview.ws.params.AutoCalcSetting; -import java.awt.Color; import java.awt.Container; +import java.awt.Dimension; import java.awt.Font; +import java.awt.FontMetrics; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Hashtable; -import java.util.Stack; -import java.util.Vector; +import java.util.Iterator; +import java.util.List; + +import javax.swing.JInternalFrame; /** * DOCUMENT ME! @@ -72,82 +70,29 @@ import java.util.Vector; * @author $author$ * @version $Revision: 1.141 $ */ -public class AlignViewport extends AlignmentViewport implements - SelectionSource, VamsasSource, AlignViewportI +public class AlignViewport extends AlignmentViewport + implements SelectionSource { - int startRes; - - int endRes; - - int startSeq; - - int endSeq; - - boolean showJVSuffix = true; - - boolean showText = true; - - boolean showColourText = false; - - boolean showBoxes = true; - - boolean wrapAlignment = false; - - boolean renderGaps = true; - - boolean showSequenceFeatures = false; - - boolean showAnnotation = true; - - int charHeight; - - int charWidth; - - boolean validCharWidth; - - int wrappedWidth; - Font font; - boolean seqNameItalics; - - NJTree currentTree = null; - - boolean scaleAboveWrapped = false; - - boolean scaleLeftWrapped = true; - - boolean scaleRightWrapped = true; - - boolean showHiddenMarkers = true; - boolean cursorMode = false; - /** - * Keys are the feature types which are currently visible. Note: Values are - * not used! - */ - private Hashtable featuresDisplayed = null; - boolean antiAlias = false; - Rectangle explodedPosition; - - String viewName; + private Rectangle explodedGeometry = null; - boolean gatherViewsHere = false; + private String viewName = null; - Stack historyList = new Stack(); - - Stack redoList = new Stack(); - - int thresholdTextColour = 0; - - Color textColour = Color.black; - - Color textColour2 = Color.white; + /* + * Flag set true on the view that should 'gather' multiple views of the same + * sequence set id when a project is reloaded. Set false on all views when + * they are 'exploded' into separate windows. Set true on the current view + * when 'Gather' is performed, and also on the first tab when the first new + * view is created. + */ + private boolean gatherViewsHere = false; - boolean rightAlignIds = false; + private AnnotationColumnChooser annotationColumnSelectionState; /** * Creates a new AlignViewport object. @@ -157,7 +102,7 @@ public class AlignViewport extends AlignmentViewport implements */ public AlignViewport(AlignmentI al) { - setAlignment(al); + super(al); init(); } @@ -175,20 +120,21 @@ public class AlignViewport extends AlignmentViewport implements public AlignViewport(AlignmentI al, String seqsetid, String viewid) { + super(al); sequenceSetID = seqsetid; viewId = viewid; // TODO remove these once 2.4.VAMSAS release finished if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null) { - Cache.log.debug("Setting viewport's sequence set id : " - + sequenceSetID); + Cache.log.debug( + "Setting viewport's sequence set id : " + sequenceSetID); } if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null) { Cache.log.debug("Setting viewport's view id : " + viewId); } - setAlignment(al); init(); + } /** @@ -199,21 +145,12 @@ public class AlignViewport extends AlignmentViewport implements * @param hiddenColumns * ColumnSelection */ - public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns) + public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns) { - setAlignment(al); + super(al); if (hiddenColumns != null) { - this.colSel = hiddenColumns; - if (hiddenColumns.getHiddenColumns() != null - && hiddenColumns.getHiddenColumns().size() > 0) - { - hasHiddenColumns = true; - } - else - { - hasHiddenColumns = false; - } + al.setHiddenColumns(hiddenColumns); } init(); } @@ -226,7 +163,7 @@ public class AlignViewport extends AlignmentViewport implements * @param seqsetid * (may be null) */ - public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns, + public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns, String seqsetid) { this(al, hiddenColumns, seqsetid, null); @@ -242,63 +179,75 @@ public class AlignViewport extends AlignmentViewport implements * @param viewid * (may be null) */ - public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns, + public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns, String seqsetid, String viewid) { + super(al); sequenceSetID = seqsetid; viewId = viewid; // TODO remove these once 2.4.VAMSAS release finished if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null) { - Cache.log.debug("Setting viewport's sequence set id : " - + sequenceSetID); + Cache.log.debug( + "Setting viewport's sequence set id : " + sequenceSetID); } if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null) { Cache.log.debug("Setting viewport's view id : " + viewId); } - setAlignment(al); + if (hiddenColumns != null) { - this.colSel = hiddenColumns; - if (hiddenColumns.getHiddenColumns() != null - && hiddenColumns.getHiddenColumns().size() > 0) - { - hasHiddenColumns = true; - } - else - { - hasHiddenColumns = false; - } + al.setHiddenColumns(hiddenColumns); } init(); } - void init() + /** + * Apply any settings saved in user preferences + */ + private void applyViewProperties() { - this.startRes = 0; - this.endRes = alignment.getWidth() - 1; - this.startSeq = 0; - this.endSeq = alignment.getHeight() - 1; + // BH! using final static strings here because we also use these in + // JS version startup api + // BH was false + antiAlias = Cache.getDefault(Preferences.ANTI_ALIAS, true); - antiAlias = Cache.getDefault("ANTI_ALIAS", false); + viewStyle.setShowJVSuffix( + Cache.getDefault(Preferences.SHOW_JVSUFFIX, true)); + setShowAnnotation(Cache.getDefault(Preferences.SHOW_ANNOTATIONS, true)); - showJVSuffix = Cache.getDefault("SHOW_JVSUFFIX", true); - showAnnotation = Cache.getDefault("SHOW_ANNOTATIONS", true); + setRightAlignIds(Cache.getDefault(Preferences.RIGHT_ALIGN_IDS, false)); + setCentreColumnLabels(Cache.getDefault(Preferences.CENTRE_COLUMN_LABELS, false)); + autoCalculateConsensusAndConservation = Cache.getDefault(Preferences.AUTO_CALC_CONSENSUS, true); - rightAlignIds = Cache.getDefault("RIGHT_ALIGN_IDS", false); - centreColumnLabels = Cache.getDefault("CENTRE_COLUMN_LABELS", false); - autoCalculateConsensus = Cache.getDefault("AUTO_CALC_CONSENSUS", true); - - setPadGaps(Cache.getDefault("PAD_GAPS", true)); - shownpfeats = Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true); - showdbrefs = Cache.getDefault("SHOW_DBREFS_TOOLTIP", true); + setPadGaps(Cache.getDefault(Preferences.PAD_GAPS, true)); + setShowNPFeats(Cache.getDefault(Preferences.SHOW_NPFEATS_TOOLTIP, true)); + setShowDBRefs(Cache.getDefault(Preferences.SHOW_DBREFS_TOOLTIP, true)); + viewStyle.setSeqNameItalics(Cache.getDefault(Preferences.ID_ITALICS, true)); + viewStyle.setWrapAlignment( + Cache.getDefault(Preferences.WRAP_ALIGNMENT, false)); + viewStyle.setShowUnconserved( + Cache.getDefault(Preferences.SHOW_UNCONSERVED, false)); + sortByTree = Cache.getDefault(Preferences.SORT_BY_TREE, false); + followSelection = Cache.getDefault(Preferences.FOLLOW_SELECTIONS, true); + sortAnnotationsBy = SequenceAnnotationOrder + .valueOf(Cache.getDefault(Preferences.SORT_ANNOTATIONS, + SequenceAnnotationOrder.NONE.name())); + showAutocalculatedAbove = Cache + .getDefault(Preferences.SHOW_AUTOCALC_ABOVE, false); + viewStyle.setScaleProteinAsCdna( + Cache.getDefault(Preferences.SCALE_PROTEIN_TO_CDNA, true)); + } - String fontName = Cache.getDefault("FONT_NAME", "SansSerif"); - String fontStyle = Cache.getDefault("FONT_STYLE", Font.PLAIN + ""); - String fontSize = Cache.getDefault("FONT_SIZE", "10"); + void init() + { + applyViewProperties(); - seqNameItalics = Cache.getDefault("ID_ITALICS", true); + String fontName = Cache.getDefault(Preferences.FONT_NAME, "SansSerif"); + String fontStyle = Cache.getDefault(Preferences.FONT_STYLE, + Font.PLAIN + ""); + String fontSize = Cache.getDefault(Preferences.FONT_SIZE, "10"); int style = 0; @@ -311,10 +260,11 @@ public class AlignViewport extends AlignmentViewport implements style = 2; } - setFont(new Font(fontName, style, Integer.parseInt(fontSize))); + setFont(new Font(fontName, style, Integer.parseInt(fontSize)), true); alignment - .setGapCharacter(Cache.getDefault("GAP_SYMBOL", "-").charAt(0)); + .setGapCharacter(Cache.getDefault(Preferences.GAP_SYMBOL, "-") + .charAt(0)); // We must set conservation and consensus before setting colour, // as Blosum and Clustal require this to be done @@ -322,124 +272,86 @@ public class AlignViewport extends AlignmentViewport implements { if (!alignment.isNucleotide()) { - showConservation = Cache.getDefault("SHOW_CONSERVATION", true); - showQuality = Cache.getDefault("SHOW_QUALITY", true); - showGroupConservation = Cache.getDefault("SHOW_GROUP_CONSERVATION", - false); + showConservation = Cache.getDefault(Preferences.SHOW_CONSERVATION, + true); + showQuality = Cache.getDefault(Preferences.SHOW_QUALITY, true); + showGroupConservation = Cache + .getDefault(Preferences.SHOW_GROUP_CONSERVATION, false); } - showConsensusHistogram = Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", - true); - showSequenceLogo = Cache.getDefault("SHOW_CONSENSUS_LOGO", false); - normaliseSequenceLogo = Cache.getDefault("NORMALISE_CONSENSUS_LOGO", + showConsensusHistogram = Cache + .getDefault(Preferences.SHOW_CONSENSUS_HISTOGRAM, true); + showSequenceLogo = Cache.getDefault(Preferences.SHOW_CONSENSUS_LOGO, false); - showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false); - showConsensus = Cache.getDefault("SHOW_IDENTITY", true); - consensus = new AlignmentAnnotation("Consensus", "PID", - new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); - consensus.hasText = true; - consensus.autoCalculated = true; + + normaliseSequenceLogo = Cache + .getDefault(Preferences.NORMALISE_CONSENSUS_LOGO, false); + showGroupConsensus = Cache + .getDefault(Preferences.SHOW_GROUP_CONSENSUS, false); + showConsensus = Cache.getDefault(Preferences.SHOW_IDENTITY, true); + + showOccupancy = Cache.getDefault(Preferences.SHOW_OCCUPANCY, true); } initAutoAnnotation(); - if (jalview.bin.Cache.getProperty("DEFAULT_COLOUR") != null) + String colourProperty = alignment.isNucleotide() + ? Preferences.DEFAULT_COLOUR_NUC + : Preferences.DEFAULT_COLOUR_PROT; + String schemeName = Cache.getProperty(colourProperty); + if (schemeName == null) { - globalColourScheme = ColourSchemeProperty.getColour(alignment, - jalview.bin.Cache.getProperty("DEFAULT_COLOUR")); - - if (globalColourScheme instanceof UserColourScheme) - { - globalColourScheme = UserDefinedColours.loadDefaultColours(); - ((UserColourScheme) globalColourScheme).setThreshold(0, - getIgnoreGapsConsensus()); - } - - if (globalColourScheme != null) - { - globalColourScheme.setConsensus(hconsensus); - } + // only DEFAULT_COLOUR available in Jalview before 2.9 + schemeName = Cache.getDefault(Preferences.DEFAULT_COLOUR, + ResidueColourScheme.NONE); } + ColourSchemeI colourScheme = ColourSchemeProperty + .getColourScheme(this, alignment, schemeName); + residueShading = new ResidueShader(colourScheme); - wrapAlignment = jalview.bin.Cache.getDefault("WRAP_ALIGNMENT", false); - showUnconserved = jalview.bin.Cache.getDefault("SHOW_UNCONSERVED", - false); - sortByTree = jalview.bin.Cache.getDefault("SORT_BY_TREE", false); - followSelection = jalview.bin.Cache.getDefault("FOLLOW_SELECTIONS", - true); - } + if (colourScheme instanceof UserColourScheme) + { + residueShading = new ResidueShader( + UserDefinedColours.loadDefaultColours()); + residueShading.setThreshold(0, isIgnoreGapsConsensus()); + } - /** - * set the flag - * - * @param b - * features are displayed if true - */ - public void setShowSequenceFeatures(boolean b) - { - showSequenceFeatures = b; + if (residueShading != null) + { + residueShading.setConsensus(hconsensus); + } + setColourAppliesToAllGroups(true); } - public boolean getShowSequenceFeatures() - { - return showSequenceFeatures; - } + boolean validCharWidth; /** - * centre columnar annotation labels in displayed alignment annotation TODO: - * add to jalviewXML and annotation display settings + * {@inheritDoc} */ - boolean centreColumnLabels = false; - - private boolean showdbrefs; - - private boolean shownpfeats; + @Override + public void setFont(Font f, boolean setGrid) + { + font = f; - // --------END Structure Conservation + Container c = new Container(); - /** - * get the consensus sequence as displayed under the PID consensus annotation - * row. - * - * @return consensus sequence as a new sequence object - */ - public SequenceI getConsensusSeq() - { - if (consensus == null) - { - updateConsensus(null); - } - if (consensus == null) - { - return null; - } - StringBuffer seqs = new StringBuffer(); - for (int i = 0; i < consensus.annotations.length; i++) + if (setGrid) { - if (consensus.annotations[i] != null) - { - if (consensus.annotations[i].description.charAt(0) == '[') - { - seqs.append(consensus.annotations[i].description.charAt(1)); - } - else - { - seqs.append(consensus.annotations[i].displayCharacter); - } - } + FontMetrics fm = c.getFontMetrics(font); + int ww = fm.charWidth('M'); + setCharHeight(fm.getHeight()); + setCharWidth(ww); } + viewStyle.setFontName(font.getName()); + viewStyle.setFontStyle(font.getStyle()); + viewStyle.setFontSize(font.getSize()); - SequenceI sq = new Sequence("Consensus", seqs.toString()); - sq.setDescription("Percentage Identity Consensus " - + ((ignoreGapsInConsensusCalculation) ? " without gaps" : "")); - return sq; + validCharWidth = true; } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public int getStartRes() + @Override + public void setViewStyle(ViewStyleI settingsForView) { - return startRes; + super.setViewStyle(settingsForView); + setFont(new Font(viewStyle.getFontName(), viewStyle.getFontStyle(), + viewStyle.getFontSize()), false); } /** @@ -447,831 +359,796 @@ public class AlignViewport extends AlignmentViewport implements * * @return DOCUMENT ME! */ - public int getEndRes() + public Font getFont() { - return endRes; + return font; } /** * DOCUMENT ME! * - * @return DOCUMENT ME! + * @param align + * DOCUMENT ME! */ - public int getStartSeq() + @Override + public void setAlignment(AlignmentI align) { - return startSeq; + replaceMappings(align); + super.setAlignment(align); } /** - * DOCUMENT ME! + * Replace any codon mappings for this viewport with those for the given + * viewport * - * @param res - * DOCUMENT ME! + * @param align */ - public void setStartRes(int res) + public void replaceMappings(AlignmentI align) + { + + /* + * Deregister current mappings (if any) + */ + deregisterMappings(); + + /* + * Register new mappings (if any) + */ + if (align != null) + { + Desktop.getStructureSelectionManager() + .registerMappings(align.getCodonFrames()); + } + + /* + * replace mappings on our alignment + */ + if (alignment != null && align != null) + { + alignment.setCodonFrames(align.getCodonFrames()); + } + } + + protected void deregisterMappings() { - this.startRes = res; + AlignmentI al = getAlignment(); + if (al != null) + { + List mappings = al.getCodonFrames(); + if (mappings != null) + { + StructureSelectionManager ssm = Desktop + .getStructureSelectionManager(); + for (AlignedCodonFrame acf : mappings) + { + if (noReferencesTo(acf)) + { + ssm.deregisterMapping(acf); + } + } + } + } } /** * DOCUMENT ME! * - * @param seq - * DOCUMENT ME! + * @return DOCUMENT ME! */ - public void setStartSeq(int seq) + @Override + public char getGapCharacter() { - this.startSeq = seq; + return getAlignment().getGapCharacter(); } /** * DOCUMENT ME! * - * @param res + * @param gap * DOCUMENT ME! */ - public void setEndRes(int res) + public void setGapCharacter(char gap) { - if (res > (alignment.getWidth() - 1)) - { - // log.System.out.println(" Corrected res from " + res + " to maximum " + - // (alignment.getWidth()-1)); - res = alignment.getWidth() - 1; - } - - if (res < 0) + if (getAlignment() != null) { - res = 0; + getAlignment().setGapCharacter(gap); } - - this.endRes = res; } /** - * DOCUMENT ME! + * returns the visible column regions of the alignment * - * @param seq - * DOCUMENT ME! + * @param selectedRegionOnly + * true to just return the contigs intersecting with the selected + * area + * @return */ - public void setEndSeq(int seq) + public Iterator getViewAsVisibleContigs(boolean selectedRegionOnly) { - if (seq > alignment.getHeight()) + int start = 0; + int end = 0; + if (selectedRegionOnly && selectionGroup != null) { - seq = alignment.getHeight(); + start = selectionGroup.getStartRes(); + end = selectionGroup.getEndRes() + 1; } - - if (seq < 0) + else { - seq = 0; + end = alignment.getWidth(); } - - this.endSeq = seq; + return (alignment.getHiddenColumns().getVisContigsIterator(start, end, + false)); } /** - * DOCUMENT ME! + * get hash of undo and redo list for the alignment * - * @return DOCUMENT ME! + * @return long[] { historyList.hashCode, redoList.hashCode }; */ - public int getEndSeq() + public long[] getUndoRedoHash() { - return endSeq; + // TODO: JAL-1126 + if (historyList == null || redoList == null) + { + return new long[] { -1, -1 }; + } + return new long[] { historyList.hashCode(), this.redoList.hashCode() }; } /** - * DOCUMENT ME! + * test if a particular set of hashcodes are different to the hashcodes for + * the undo and redo list. * - * @param f - * DOCUMENT ME! + * @param undoredo + * the stored set of hashcodes as returned by getUndoRedoHash + * @return true if the hashcodes differ (ie the alignment has been edited) or + * the stored hashcode array differs in size */ - public void setFont(Font f) + public boolean isUndoRedoHashModified(long[] undoredo) { - font = f; - - Container c = new Container(); + if (undoredo == null) + { + return true; + } + long[] cstate = getUndoRedoHash(); + if (cstate.length != undoredo.length) + { + return true; + } - java.awt.FontMetrics fm = c.getFontMetrics(font); - setCharHeight(fm.getHeight()); - setCharWidth(fm.charWidth('M')); - validCharWidth = true; + for (int i = 0; i < cstate.length; i++) + { + if (cstate[i] != undoredo[i]) + { + return true; + } + } + return false; } + public boolean followSelection = true; + /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * @return true if view selection should always follow the selections + * broadcast by other selection sources */ - public Font getFont() + public boolean getFollowSelection() { - return font; + return followSelection; } /** - * DOCUMENT ME! - * - * @param w - * DOCUMENT ME! + * Send the current selection to be broadcast to any selection listeners. */ - public void setCharWidth(int w) + @Override + public void sendSelection() { - this.charWidth = w; + Desktop.getStructureSelectionManager().sendSelection( + new SequenceGroup(getSelectionGroup()), + new ColumnSelection(getColumnSelection()), + new HiddenColumns(getAlignment().getHiddenColumns()), this); } /** - * DOCUMENT ME! + * return the alignPanel containing the given viewport. Use this to get the + * components currently handling the given viewport. * - * @return DOCUMENT ME! + * @param av + * @return null or an alignPanel guaranteed to have non-null alignFrame + * reference */ - public int getCharWidth() + public AlignmentPanel getAlignPanel() { - return charWidth; + AlignmentPanel[] aps = PaintRefresher + .getAssociatedPanels(this.getSequenceSetId()); + for (int p = 0; aps != null && p < aps.length; p++) + { + if (aps[p].av == this) + { + return aps[p]; + } + } + return null; } - /** - * DOCUMENT ME! - * - * @param h - * DOCUMENT ME! - */ - public void setCharHeight(int h) + public boolean getSortByTree() { - this.charHeight = h; + return sortByTree; } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public int getCharHeight() + public void setSortByTree(boolean sort) { - return charHeight; + sortByTree = sort; } /** - * DOCUMENT ME! - * - * @param w - * DOCUMENT ME! + * Returns the (Desktop) instance of the StructureSelectionManager */ - public void setWrappedWidth(int w) + @Override + public StructureSelectionManager getStructureSelectionManager() { - this.wrappedWidth = w; + return Desktop.getStructureSelectionManager(); } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public int getWrappedWidth() + @Override + public boolean isNormaliseSequenceLogo() { - return wrappedWidth; + return normaliseSequenceLogo; } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public AlignmentI getAlignment() + public void setNormaliseSequenceLogo(boolean state) { - return alignment; + normaliseSequenceLogo = state; } /** - * DOCUMENT ME! * - * @param align - * DOCUMENT ME! - */ - public void setAlignment(AlignmentI align) - { - if (alignment != null && alignment.getCodonFrames() != null) - { - StructureSelectionManager.getStructureSelectionManager( - Desktop.instance).removeMappings(alignment.getCodonFrames()); - } - this.alignment = align; - if (alignment != null && alignment.getCodonFrames() != null) - { - StructureSelectionManager.getStructureSelectionManager( - Desktop.instance).addMappings(alignment.getCodonFrames()); - } - } - - /** - * DOCUMENT ME! - * - * @param state - * DOCUMENT ME! - */ - public void setWrapAlignment(boolean state) - { - wrapAlignment = state; - } - - /** - * DOCUMENT ME! - * - * @param state - * DOCUMENT ME! - */ - public void setShowText(boolean state) - { - showText = state; - } - - /** - * DOCUMENT ME! - * - * @param state - * DOCUMENT ME! + * @return true if alignment characters should be displayed */ - public void setRenderGaps(boolean state) + @Override + public boolean isValidCharWidth() { - renderGaps = state; + return validCharWidth; } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean getColourText() - { - return showColourText; - } + private Hashtable calcIdParams = new Hashtable<>(); - /** - * DOCUMENT ME! - * - * @param state - * DOCUMENT ME! - */ - public void setColourText(boolean state) + public AutoCalcSetting getCalcIdSettingsFor(String calcId) { - showColourText = state; + return calcIdParams.get(calcId); } - /** - * DOCUMENT ME! - * - * @param state - * DOCUMENT ME! - */ - public void setShowBoxes(boolean state) + public void setCalcIdSettingsFor(String calcId, AutoCalcSetting settings, + boolean needsUpdate) { - showBoxes = state; + calcIdParams.put(calcId, settings); + // TODO: create a restart list to trigger any calculations that need to be + // restarted after load + // calculator.getRegisteredWorkersOfClass(settings.getWorkerClass()) + if (needsUpdate) + { + Cache.log.debug("trigger update for " + calcId); + } } /** - * DOCUMENT ME! + * Method called when another alignment's edit (or possibly other) command is + * broadcast to here. + * + * To allow for sequence mappings (e.g. protein to cDNA), we have to first + * 'unwind' the command on the source sequences (in simulation, not in fact), + * and then for each edit in turn: + *
    + *
  • compute the equivalent edit on the mapped sequences
  • + *
  • apply the mapped edit
  • + *
  • 'apply' the source edit to the working copy of the source + * sequences
  • + *
* - * @return DOCUMENT ME! - */ - public boolean getWrapAlignment() - { - return wrapAlignment; - } + * @param command + * @param undo + * @param ssm + */ + @Override + public void mirrorCommand(CommandI command, boolean undo, + StructureSelectionManager ssm, VamsasSource source) + { + /* + * Do nothing unless we are a 'complement' of the source. May replace this + * with direct calls not via SSM. + */ + if (source instanceof AlignViewportI + && ((AlignViewportI) source).getCodingComplement() == this) + { + // ok to continue; + } + else + { + return; + } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean getShowText() - { - return showText; + CommandI mappedCommand = ssm.mapCommand(command, undo, getAlignment(), + getGapCharacter()); + if (mappedCommand != null) + { + AlignmentI[] views = getAlignPanel().alignFrame.getViewAlignments(); + mappedCommand.doCommand(views); + getAlignPanel().alignmentChanged(); + } } /** - * DOCUMENT ME! + * Add the sequences from the given alignment to this viewport. Optionally, + * may give the user the option to open a new frame, or split panel, with cDNA + * and protein linked. * - * @return DOCUMENT ME! - */ - public boolean getShowBoxes() - { - return showBoxes; + * @param toAdd + * @param title + */ + public void addAlignment(AlignmentI toAdd, String title) + { + // TODO: promote to AlignViewportI? applet CutAndPasteTransfer is different + + // JBPComment: title is a largely redundant parameter at the moment + // JBPComment: this really should be an 'insert/pre/append' controller + // JBPComment: but the DNA/Protein check makes it a bit more complex + + // refactored from FileLoader / CutAndPasteTransfer / SequenceFetcher with + // this comment: + // TODO: create undo object for this JAL-1101 + + /* + * Ensure datasets are created for the new alignment as + * mappings operate on dataset sequences + */ + toAdd.setDataset(null); + + /* + * Check if any added sequence could be the object of a mapping or + * cross-reference; if so, make the mapping explicit + */ + getAlignment().realiseMappings(toAdd.getSequences()); + + /* + * If any cDNA/protein mappings exist or can be made between the alignments, + * offer to open a split frame with linked alignments + */ + if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true)) + { + if (AlignmentUtils.isMappable(toAdd, getAlignment())) + { + openLinkedAlignment(toAdd, title); + return; + } + } + addDataToAlignment(toAdd); } /** - * DOCUMENT ME! + * adds sequences to this alignment * - * @return DOCUMENT ME! + * @param toAdd */ - public char getGapCharacter() + void addDataToAlignment(AlignmentI toAdd) { - return getAlignment().getGapCharacter(); - } + // TODO: JAL-407 regardless of above - identical sequences (based on ID and + // provenance) should share the same dataset sequence - /** - * DOCUMENT ME! - * - * @param gap - * DOCUMENT ME! - */ - public void setGapCharacter(char gap) - { - if (getAlignment() != null) + AlignmentI al = getAlignment(); + String gap = String.valueOf(al.getGapCharacter()); + for (int i = 0; i < toAdd.getHeight(); i++) { - getAlignment().setGapCharacter(gap); + SequenceI seq = toAdd.getSequenceAt(i); + /* + * experimental! + * - 'align' any mapped sequences as per existing + * e.g. cdna to genome, domain hit to protein sequence + * very experimental! (need a separate menu option for this) + * - only add mapped sequences ('select targets from a dataset') + */ + if (true /*AlignmentUtils.alignSequenceAs(seq, al, gap, true, true)*/) + { + al.addSequence(seq); + } } - } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public ColumnSelection getColumnSelection() - { - return colSel; + ranges.setEndSeq(getAlignment().getHeight() - 1); // BH 2019.04.18 + firePropertyChange("alignment", null, getAlignment().getSequences()); } - /** - * DOCUMENT ME! - * - * @param tree - * DOCUMENT ME! - */ - public void setCurrentTree(NJTree tree) - { - currentTree = tree; - } + public final static int NO_SPLIT = 0; - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public NJTree getCurrentTree() - { - return currentTree; - } + public final static int SPLIT_FRAME = 1; - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean getShowJVSuffix() - { - return showJVSuffix; - } + public final static int NEW_WINDOW = 2; /** - * DOCUMENT ME! + * Show a dialog with the option to open and link (cDNA <-> protein) as a new + * alignment, either as a standalone alignment or in a split frame. Returns + * true if the new alignment was opened, false if not, because the user + * declined the offer. * - * @param b - * DOCUMENT ME! - */ - public void setShowJVSuffix(boolean b) - { - showJVSuffix = b; - } - - /** - * DOCUMENT ME! + * @param al + * @param title + */ + protected void openLinkedAlignment(AlignmentI al, String title) + { + String[] options = new String[] { MessageManager.getString("action.no"), + MessageManager.getString("label.split_window"), + MessageManager.getString("label.new_window"), }; + final String question = JvSwingUtils.wrapTooltip(true, + MessageManager.getString("label.open_split_window?")); + + /* + * options No, Split Window, New Window correspond to + * dialog responses 0, 1, 2 (even though JOptionPane shows them + * in reverse order) + */ + JvOptionPane dialog = JvOptionPane + .newOptionDialog(Desktop.getDesktopPane()) + .setResponseHandler(NO_SPLIT, new Runnable() + { + @Override + public void run() + { + addDataToAlignment(al); + } + }).setResponseHandler(SPLIT_FRAME, new Runnable() + { + @Override + public void run() + { + openLinkedAlignmentAs(getAlignPanel().alignFrame, + new Alignment(getAlignment()), al, title, + SPLIT_FRAME); + } + }).setResponseHandler(NEW_WINDOW, new Runnable() + { + @Override + public void run() + { + openLinkedAlignmentAs(null, getAlignment(), al, title, + NEW_WINDOW); + } + }); + dialog.showDialog(question, + MessageManager.getString("label.open_split_window"), + JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null, + options, options[0]); + } + + /** + * Open a split frame or a new window * - * @return DOCUMENT ME! - */ - public boolean getShowAnnotation() - { - return showAnnotation; - } + * @param al + * @param title + * @param mode + * SPLIT_FRAME or NEW_WINDOW + */ + public static void openLinkedAlignmentAs(AlignFrame thisFrame, + AlignmentI thisAlignment, AlignmentI al, String title, int mode) + { + // BH: thisAlignment is already a copy if mode == SPLIT_FRAME + // Identify protein and dna alignments. Make a copy of this one if opening + // in a new split pane. + + AlignmentI protein = al.isNucleotide() ? thisAlignment : al; + AlignmentI cdna = al.isNucleotide() ? al : thisAlignment; + + /* + * Map sequences. At least one should get mapped as we have already passed + * the test for 'mappability'. Any mappings made will be added to the + * protein alignment. Note creating dataset sequences on the new alignment + * is a pre-requisite for building mappings. + */ + al.setDataset(null); + AlignmentUtils.mapProteinAlignmentToCdna(protein, cdna); + + /* + * Create the AlignFrame for the added alignment. If it is protein, mappings + * are registered with StructureSelectionManager as a side-effect. + */ + AlignFrame newAlignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); + newAlignFrame.setTitle(title); + newAlignFrame.setStatus(MessageManager + .formatMessage("label.successfully_loaded_file", new Object[] + { title })); + + // TODO if we want this (e.g. to enable reload of the alignment from file), + // we will need to add parameters to the stack. + // if (!protocol.equals(DataSourceType.PASTE)) + // { + // alignFrame.setFileName(file, format); + // } + + if (mode == NEW_WINDOW) + { + Desktop.addInternalFrame(newAlignFrame, title, + AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); + } - /** - * DOCUMENT ME! - * - * @param b - * DOCUMENT ME! - */ - public void setShowAnnotation(boolean b) - { - showAnnotation = b; - } + try + { + newAlignFrame.setMaximum(Cache.getDefault(Preferences.SHOW_FULLSCREEN, false)); + } catch (java.beans.PropertyVetoException ex) + { + } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean getScaleAboveWrapped() - { - return scaleAboveWrapped; + if (mode == SPLIT_FRAME) + { + al.alignAs(thisAlignment); + openSplitFrame(thisFrame, newAlignFrame, thisAlignment); + } } /** - * DOCUMENT ME! + * Helper method to open a new SplitFrame holding linked dna and protein + * alignments. * - * @return DOCUMENT ME! + * @param newAlignFrame + * containing a new alignment to be shown + * @param complement + * cdna/protein complement alignment to show in the other split half + * @return the protein alignment in the split frame */ - public boolean getScaleLeftWrapped() + static protected AlignmentI openSplitFrame(AlignFrame thisFrame, + AlignFrame newAlignFrame, AlignmentI complement) { - return scaleLeftWrapped; - } + /* + * Make a new frame with a copy of the alignment we are adding to. If this + * is protein, the mappings to cDNA will be registered with + * StructureSelectionManager as a side-effect. + */ + AlignFrame copyMe = new AlignFrame(complement, AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); + copyMe.setTitle(thisFrame.getTitle()); - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean getScaleRightWrapped() - { - return scaleRightWrapped; + AlignmentI al = newAlignFrame.viewport.getAlignment(); + final AlignFrame proteinFrame = al.isNucleotide() ? copyMe + : newAlignFrame; + final AlignFrame cdnaFrame = al.isNucleotide() ? newAlignFrame : copyMe; + cdnaFrame.setVisible(true); + proteinFrame.setVisible(true); + String linkedTitle = MessageManager + .getString("label.linked_view_title"); + + /* + * Open in split pane. DNA sequence above, protein below. + */ + JInternalFrame splitFrame = new SplitFrame(cdnaFrame, proteinFrame); + Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1); + + return proteinFrame.viewport.getAlignment(); } - /** - * DOCUMENT ME! - * - * @param b - * DOCUMENT ME! - */ - public void setScaleAboveWrapped(boolean b) + public AnnotationColumnChooser getAnnotationColumnSelectionState() { - scaleAboveWrapped = b; + return annotationColumnSelectionState; } - /** - * DOCUMENT ME! - * - * @param b - * DOCUMENT ME! - */ - public void setScaleLeftWrapped(boolean b) + public void setAnnotationColumnSelectionState( + AnnotationColumnChooser currentAnnotationColumnSelectionState) { - scaleLeftWrapped = b; + this.annotationColumnSelectionState = currentAnnotationColumnSelectionState; } - /** - * DOCUMENT ME! - * - * @param b - * DOCUMENT ME! - */ - public void setScaleRightWrapped(boolean b) + @Override + public void setIdWidth(int i) { - scaleRightWrapped = b; + super.setIdWidth(i); + AlignmentPanel ap = getAlignPanel(); + if (ap != null) + { + // modify GUI elements to reflect geometry change + Dimension idw = ap.getIdPanel().getIdCanvas().getPreferredSize(); + idw.width = i; + ap.getIdPanel().getIdCanvas().setPreferredSize(idw); + } } - public void setDataset(boolean b) + public Rectangle getExplodedGeometry() { - isDataset = b; + return explodedGeometry; } - public boolean isDataset() + public void setExplodedGeometry(Rectangle explodedPosition) { - return isDataset; + this.explodedGeometry = explodedPosition; } - public boolean getShowHiddenMarkers() + public boolean isGatherViewsHere() { - return showHiddenMarkers; + return gatherViewsHere; } - public void setShowHiddenMarkers(boolean show) + public void setGatherViewsHere(boolean gatherViewsHere) { - showHiddenMarkers = show; + this.gatherViewsHere = gatherViewsHere; } /** - * returns the visible column regions of the alignment - * - * @param selectedRegionOnly - * true to just return the contigs intersecting with the selected - * area - * @return + * If this viewport has a (Protein/cDNA) complement, then scroll the + * complementary alignment to match this one. */ - public int[] getViewAsVisibleContigs(boolean selectedRegionOnly) + public void scrollComplementaryAlignment() { - int[] viscontigs = null; - int start = 0, end = 0; - if (selectedRegionOnly && selectionGroup != null) + /* + * Populate a SearchResults object with the mapped location to scroll to. If + * there is no complement, or it is not following highlights, or no mapping + * is found, the result will be empty. + */ + SearchResultsI sr = new SearchResults(); + int verticalOffset = findComplementScrollTarget(sr); + if (!sr.isEmpty()) { - start = selectionGroup.getStartRes(); - end = selectionGroup.getEndRes() + 1; + // TODO would like next line without cast but needs more refactoring... + final AlignmentPanel complementPanel = ((AlignViewport) getCodingComplement()) + .getAlignPanel(); + complementPanel.setToScrollComplementPanel(false); + complementPanel.scrollToCentre(sr, verticalOffset); + complementPanel.setToScrollComplementPanel(true); } - else - { - end = alignment.getWidth(); - } - viscontigs = colSel.getVisibleContigs(start, end); - return viscontigs; } /** - * get hash of undo and redo list for the alignment + * Answers true if no alignment holds a reference to the given mapping * - * @return long[] { historyList.hashCode, redoList.hashCode }; - */ - public long[] getUndoRedoHash() - { - // TODO: JAL-1126 - if (historyList == null || redoList == null) - return new long[] - { -1, -1 }; - return new long[] - { historyList.hashCode(), this.redoList.hashCode() }; - } - - /** - * test if a particular set of hashcodes are different to the hashcodes for - * the undo and redo list. - * - * @param undoredo - * the stored set of hashcodes as returned by getUndoRedoHash - * @return true if the hashcodes differ (ie the alignment has been edited) or - * the stored hashcode array differs in size + * @param acf + * @return */ - public boolean isUndoRedoHashModified(long[] undoredo) + protected boolean noReferencesTo(AlignedCodonFrame acf) { - if (undoredo == null) - { - return true; - } - long[] cstate = getUndoRedoHash(); - if (cstate.length != undoredo.length) + AlignFrame[] frames = Desktop.getAlignFrames(); + if (frames == null) { return true; } - - for (int i = 0; i < cstate.length; i++) + for (AlignFrame af : frames) { - if (cstate[i] != undoredo[i]) + if (!af.isClosed()) { - return true; + for (AlignmentViewPanel ap : af.getAlignPanels()) + { + AlignmentI al = ap.getAlignment(); + if (al != null && al.getCodonFrames().contains(acf)) + { + return false; + } + } } } - return false; - } - - public boolean getCentreColumnLabels() - { - return centreColumnLabels; - } - - public void setCentreColumnLabels(boolean centrecolumnlabels) - { - centreColumnLabels = centrecolumnlabels; - } - - /** - * enable or disable the display of Database Cross References in the sequence - * ID tooltip - */ - public void setShowDbRefs(boolean show) - { - showdbrefs = show; - } - - /** - * - * @return true if Database References are to be displayed on tooltips. - */ - public boolean isShowDbRefs() - { - return showdbrefs; - } - - /** - * - * @return true if Non-positional features are to be displayed on tooltips. - */ - public boolean isShowNpFeats() - { - return shownpfeats; + return true; } /** - * enable or disable the display of Non-Positional sequence features in the - * sequence ID tooltip + * Applies the supplied feature settings descriptor to currently known + * features. This supports an 'initial configuration' of feature colouring + * based on a preset or user favourite. This may then be modified in the usual + * way using the Feature Settings dialogue. * - * @param show + * @param featureSettings */ - public void setShowNpFeats(boolean show) + @Override + public void applyFeaturesStyle(FeatureSettingsModelI featureSettings) { - shownpfeats = show; + transferFeaturesStyles(featureSettings, false); } /** + * Applies the supplied feature settings descriptor to currently known features. + * This supports an 'initial configuration' of feature colouring based on a + * preset or user favourite. This may then be modified in the usual way using + * the Feature Settings dialogue. * - * @return true if view has hidden rows + * @param featureSettings */ - public boolean hasHiddenRows() + @Override + public void mergeFeaturesStyle(FeatureSettingsModelI featureSettings) { - return hasHiddenRows; + transferFeaturesStyles(featureSettings, true); } /** + * when mergeOnly is set, then group and feature visibility or feature colours + * are not modified for features and groups already known to the feature + * renderer. Feature ordering is always adjusted, and transparency is always set + * regardless. * - * @return true if view has hidden columns - */ - public boolean hasHiddenColumns() - { - return hasHiddenColumns; - } - - /** - * when set, view will scroll to show the highlighted position - */ - public boolean followHighlight = true; - - /** - * @return true if view should scroll to show the highlighted region of a - * sequence - * @return - */ - public boolean getFollowHighlight() - { - return followHighlight; - } - - public boolean followSelection = true; - - /** - * @return true if view selection should always follow the selections - * broadcast by other selection sources + * @param featureSettings + * @param mergeOnly */ - public boolean getFollowSelection() - { - return followSelection; - } - - boolean showSeqFeaturesHeight; - - public void sendSelection() + private void transferFeaturesStyles(FeatureSettingsModelI featureSettings, + boolean mergeOnly) { - jalview.structure.StructureSelectionManager - .getStructureSelectionManager(Desktop.instance).sendSelection( - new SequenceGroup(getSelectionGroup()), - new ColumnSelection(getColumnSelection()), this); - } - - public void setShowSequenceFeaturesHeight(boolean selected) - { - showSeqFeaturesHeight = selected; - } - - public boolean getShowSequenceFeaturesHeight() - { - return showSeqFeaturesHeight; - } - - /** - * return the alignPanel containing the given viewport. Use this to get the - * components currently handling the given viewport. - * - * @param av - * @return null or an alignPanel guaranteed to have non-null alignFrame - * reference - */ - public AlignmentPanel getAlignPanel() - { - AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(this - .getSequenceSetId()); - AlignmentPanel ap = null; - for (int p = 0; aps != null && p < aps.length; p++) + if (featureSettings == null) { - if (aps[p].av == this) - { - return aps[p]; - } + return; } - return null; - } - - public boolean getSortByTree() - { - return sortByTree; - } - public void setSortByTree(boolean sort) - { - sortByTree = sort; - } - - /** - * synthesize a column selection if none exists so it covers the given - * selection group. if wholewidth is false, no column selection is made if the - * selection group covers the whole alignment width. - * - * @param sg - * @param wholewidth - */ - public void expandColSelection(SequenceGroup sg, boolean wholewidth) - { - int sgs, sge; - if (sg != null - && (sgs = sg.getStartRes()) >= 0 - && sg.getStartRes() <= (sge = sg.getEndRes()) - && (colSel == null || colSel.getSelected() == null || colSel - .getSelected().size() == 0)) + FeatureRenderer fr = getAlignPanel().getSeqPanel().seqCanvas + .getFeatureRenderer(); + List origRenderOrder = new ArrayList<>(), + origGroups = new ArrayList<>(); + // preserve original render order - allows differentiation between user configured colours and autogenerated ones + origRenderOrder.addAll(fr.getRenderOrder()); + origGroups.addAll(fr.getFeatureGroups()); + + fr.findAllFeatures(true); + List renderOrder = fr.getRenderOrder(); + FeaturesDisplayedI displayed = fr.getFeaturesDisplayed(); + if (!mergeOnly) { - if (!wholewidth && alignment.getWidth() == (1 + sge - sgs)) + // only clear displayed features if we are merging + displayed.clear(); + } + // TODO this clears displayed.featuresRegistered - do we care? + // + // JAL-3330 - JBP - yes we do - calling applyFeatureStyle to a view where + // feature visibility has already been configured is not very friendly + /* + * set feature colour if specified by feature settings + * set visibility of all features + */ + for (String type : renderOrder) + { + FeatureColourI preferredColour = featureSettings + .getFeatureColour(type); + FeatureColourI origColour = fr.getFeatureStyle(type); + if (!mergeOnly || (!origRenderOrder.contains(type) + || origColour == null + || (!origColour.isGraduatedColour() + && origColour.getColour() != null + && origColour.getColour().equals( + ColorUtils.createColourFromName(type))))) { - // do nothing - return; - } - if (colSel == null) + // if we are merging, only update if there wasn't already a colour defined for + // this type + if (preferredColour != null) { - colSel = new ColumnSelection(); + fr.setColour(type, preferredColour); } - for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++) + if (featureSettings.isFeatureDisplayed(type)) { - colSel.addElement(cspos); + displayed.setVisible(type); } } - } - - public StructureSelectionManager getStructureSelectionManager() - { - return StructureSelectionManager - .getStructureSelectionManager(Desktop.instance); - } + } - /** - * - * @param pdbEntries - * @return a series of SequenceI arrays, one for each PDBEntry, listing which - * sequence in the alignment holds a reference to it - */ - public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries) - { - ArrayList seqvectors = new ArrayList(); - for (PDBEntry pdb : pdbEntries) + /* + * set visibility of feature groups + */ + for (String group : fr.getFeatureGroups()) { - ArrayList seqs = new ArrayList(); - for (int i = 0; i < alignment.getHeight(); i++) + if (!mergeOnly || !origGroups.contains(group)) { - Vector pdbs = alignment.getSequenceAt(i).getDatasetSequence() - .getPDBId(); - if (pdbs == null) - continue; - SequenceI sq; - for (int p = 0; p < pdbs.size(); p++) - { - PDBEntry p1 = (PDBEntry) pdbs.elementAt(p); - if (p1.getId().equals(pdb.getId())) - { - if (!seqs.contains(sq = alignment.getSequenceAt(i))) - seqs.add(sq); - - continue; - } - } + // when merging, display groups only if the aren't already marked as not visible + fr.setGroupVisibility(group, + featureSettings.isGroupDisplayed(group)); } - seqvectors.add(seqs.toArray(new SequenceI[seqs.size()])); } - return seqvectors.toArray(new SequenceI[seqvectors.size()][]); - } - - public boolean isNormaliseSequenceLogo() - { - return normaliseSequenceLogo; - } - - public void setNormaliseSequenceLogo(boolean state) - { - normaliseSequenceLogo = state; - } - - /** - * - * @return true if alignment characters should be displayed - */ - public boolean isValidCharWidth() - { - return validCharWidth; - } - - private Hashtable calcIdParams = new Hashtable(); - - public AutoCalcSetting getCalcIdSettingsFor(String calcId) - { - return calcIdParams.get(calcId); - } - public void setCalcIdSettingsFor(String calcId, AutoCalcSetting settings, - boolean needsUpdate) - { - calcIdParams.put(calcId, settings); - // TODO: create a restart list to trigger any calculations that need to be - // restarted after load - // calculator.getRegisteredWorkersOfClass(settings.getWorkerClass()) - if (needsUpdate) + /* + * order the features + */ + if (featureSettings.optimiseOrder()) { - Cache.log.debug("trigger update for " + calcId); + // TODO not supported (yet?) + } + else + { + fr.orderFeatures(featureSettings); } + fr.setTransparency(featureSettings.getTransparency()); } - public Hashtable getFeaturesDisplayed() + public String getViewName() { - return featuresDisplayed; + return viewName; } - public void setFeaturesDisplayed(Hashtable featuresDisplayed) + public void setViewName(String viewName) { - this.featuresDisplayed = featuresDisplayed; + this.viewName = viewName; } }