X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Frenderer%2Fseqfeatures%2FFeatureRenderer.java;h=9e0089f98cbdfd2ef9d6bf221a90f1b782036a2f;hb=b9867dd3b0aeaa0fcb839b59cadbb1f76309cb5e;hp=909ee103bf86fe485b6f0155f1a1c2ff0ba3a1d0;hpb=72b3f05a1157da32ada5aea139139996dddea219;p=jalview.git diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java index 909ee10..9e0089f 100644 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@ -1,7 +1,29 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview 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 3 + * of the License, or (at your option) any later version. + * + * Jalview 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 Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.renderer.seqfeatures; +import jalview.api.AlignViewportI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.awt.AlphaComposite; import java.awt.Color; @@ -10,8 +32,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; -public class FeatureRenderer extends - jalview.viewmodel.seqfeatures.FeatureRendererModel +public class FeatureRenderer extends FeatureRendererModel { FontMetrics fm; @@ -20,28 +41,6 @@ public class FeatureRenderer extends boolean offscreenRender = false; - /** - * DOCUMENT ME! - * - * @param g - * DOCUMENT ME! - * @param seq - * DOCUMENT ME! - * @param sg - * DOCUMENT ME! - * @param start - * DOCUMENT ME! - * @param end - * DOCUMENT ME! - * @param x1 - * DOCUMENT ME! - * @param y1 - * DOCUMENT ME! - * @param width - * DOCUMENT ME! - * @param height - * DOCUMENT ME! - */ protected SequenceI lastSeq; char s; @@ -52,6 +51,18 @@ public class FeatureRenderer extends boolean av_validCharWidth, av_isShowSeqFeatureHeight; + private Integer currentColour; + + /** + * Constructor given a viewport + * + * @param viewport + */ + public FeatureRenderer(AlignViewportI viewport) + { + this.av = viewport; + } + protected void updateAvConfig() { av_charHeight = av.getCharHeight(); @@ -164,56 +175,60 @@ public class FeatureRenderer extends charOffset = (av_charWidth - fm.charWidth(s)) / 2; g.drawString(String.valueOf(s), charOffset + (av_charWidth * (i - start)), pady); - } } } BufferedImage offscreenImage; + @Override public Color findFeatureColour(Color initialCol, SequenceI seq, int res) { return new Color(findFeatureColour(initialCol.getRGB(), seq, res)); } /** - * This is used by the Molecule Viewer and Overview to get the accurate - * colourof the rendered sequence + * This is used by Structure Viewers and the Overview Window to get the + * feature colour of the rendered sequence, returned as an RGB value + * + * @param defaultColour + * @param seq + * @param column + * @return */ - public synchronized int findFeatureColour(int initialCol, final SequenceI seq, - int column) + public synchronized int findFeatureColour(int defaultColour, + final SequenceI seq, int column) { if (!av.isShowSequenceFeatures()) { - return initialCol; + return defaultColour; } - final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq - .getDatasetSequence() : seq; + SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); if (seq != lastSeq) { lastSeq = seq; - sequenceFeatures = aseq.getSequenceFeatures(); - if (sequenceFeatures != null) + lastSequenceFeatures = sequenceFeatures; + if (lastSequenceFeatures != null) { - sfSize = sequenceFeatures.length; + sfSize = lastSequenceFeatures.length; } } else { - if (sequenceFeatures != lastSeq.getSequenceFeatures()) + if (lastSequenceFeatures != sequenceFeatures) { - sequenceFeatures = lastSeq.getSequenceFeatures(); - if (sequenceFeatures != null) + lastSequenceFeatures = sequenceFeatures; + if (lastSequenceFeatures != null) { - sfSize = sequenceFeatures.length; + sfSize = lastSequenceFeatures.length; } } } - if (sequenceFeatures == null || sfSize == 0) + if (lastSequenceFeatures == null || sfSize == 0) { - return initialCol; + return defaultColour; } if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column))) @@ -234,7 +249,7 @@ public class FeatureRenderer extends if (offscreenImage != null) { - offscreenImage.setRGB(0, 0, initialCol); + offscreenImage.setRGB(0, 0, defaultColour); drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0); return offscreenImage.getRGB(0, 0); @@ -245,17 +260,17 @@ public class FeatureRenderer extends if (currentColour == null) { - return initialCol; + return defaultColour; } else { - return ((Integer) currentColour).intValue(); + return currentColour.intValue(); } } } - private volatile SequenceFeature[] sequenceFeatures; + private volatile SequenceFeature[] lastSequenceFeatures; int sfSize; @@ -265,13 +280,24 @@ public class FeatureRenderer extends int epos; + /** + * Draws the sequence on the graphics context, or just determines the colour + * that would be drawn (if flag offscreenrender is true). + * + * @param g + * @param seq + * @param start + * start column (or sequence position in offscreenrender mode) + * @param end + * end column (not used in offscreenrender mode) + * @param y1 + * vertical offset at which to draw on the graphics + */ public synchronized void drawSequence(Graphics g, final SequenceI seq, int start, int end, int y1) { - final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq - .getDatasetSequence() : seq; - if (aseq.getSequenceFeatures() == null - || aseq.getSequenceFeatures().length == 0) + SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures(); + if (sequenceFeatures == null || sequenceFeatures.length == 0) { return; } @@ -284,10 +310,10 @@ public class FeatureRenderer extends updateFeatures(); if (lastSeq == null || seq != lastSeq - || aseq.getSequenceFeatures() != sequenceFeatures) + || sequenceFeatures != lastSequenceFeatures) { lastSeq = seq; - sequenceFeatures = aseq.getSequenceFeatures(); + lastSequenceFeatures = sequenceFeatures; } if (transparency != 1 && g != null) @@ -303,13 +329,11 @@ public class FeatureRenderer extends epos = lastSeq.findPosition(end); } - sfSize = sequenceFeatures.length; - String type; + sfSize = lastSequenceFeatures.length; for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++) { - type = renderOrder[renderIndex]; - - if (type == null || !showFeatureOfType(type)) + String type = renderOrder[renderIndex]; + if (!showFeatureOfType(type)) { continue; } @@ -318,90 +342,90 @@ public class FeatureRenderer extends // current feature to render for (sfindex = 0; sfindex < sfSize; sfindex++) { - if (!sequenceFeatures[sfindex].type.equals(type)) + final SequenceFeature sequenceFeature = lastSequenceFeatures[sfindex]; + if (!sequenceFeature.type.equals(type)) { continue; } - if (featureGroups != null - && sequenceFeatures[sfindex].featureGroup != null - && sequenceFeatures[sfindex].featureGroup.length() != 0 - && featureGroups - .containsKey(sequenceFeatures[sfindex].featureGroup) - && !((Boolean) featureGroups - .get(sequenceFeatures[sfindex].featureGroup)) - .booleanValue()) + if (featureGroupNotShown(sequenceFeature)) { continue; } + /* + * check feature overlaps the visible part of the alignment, + * unless doing offscreenRender (to the Overview window or a + * structure viewer) which is not limited + */ if (!offscreenRender - && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex] + && (sequenceFeature.getBegin() > epos || sequenceFeature .getEnd() < spos)) { continue; } + Color featureColour = getColour(sequenceFeature); + boolean isContactFeature = sequenceFeature.isContactFeature(); + if (offscreenRender && offscreenImage == null) { - if (sequenceFeatures[sfindex].begin <= start - && sequenceFeatures[sfindex].end >= start) + /* + * offscreen mode with no image (image is only needed if transparency + * is applied to feature colours) - just check feature is rendered at + * the requested position (start == sequence position in this mode) + */ + boolean featureIsAtPosition = sequenceFeature.begin <= start + && sequenceFeature.end >= start; + if (isContactFeature) + { + featureIsAtPosition = sequenceFeature.begin == start + || sequenceFeature.end == start; + } + if (featureIsAtPosition) { // this is passed out to the overview and other sequence renderers // (e.g. molecule viewer) to get displayed colour for rendered // sequence - currentColour = new Integer( - getColour(sequenceFeatures[sfindex]).getRGB()); + currentColour = new Integer(featureColour.getRGB()); // used to be retreived from av.featuresDisplayed // currentColour = av.featuresDisplayed // .get(sequenceFeatures[sfindex].type); } } - else if (sequenceFeatures[sfindex].type.equals("disulfide bond")) + else if (isContactFeature) { - - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - getColour(sequenceFeatures[sfindex]) - // new Color(((Integer) av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type)).intValue()) - , start, end, y1); - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]) - // new Color(((Integer) av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type)).intValue()) - , start, end, y1); + renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1, + seq.findIndex(sequenceFeature.begin) - 1, featureColour, + start, end, y1); + renderFeature(g, seq, seq.findIndex(sequenceFeature.end) - 1, + seq.findIndex(sequenceFeature.end) - 1, featureColour, + start, end, y1); } - else if (showFeature(sequenceFeatures[sfindex])) + else if (showFeature(sequenceFeature)) { if (av_isShowSeqFeatureHeight - && sequenceFeatures[sfindex].score != Float.NaN) + && !Float.isNaN(sequenceFeature.score)) { renderScoreFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1, - normaliseScore(sequenceFeatures[sfindex])); + seq.findIndex(sequenceFeature.begin) - 1, + seq.findIndex(sequenceFeature.end) - 1, + featureColour, start, end, y1, + normaliseScore(sequenceFeature)); } else { - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1); + renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1, + seq.findIndex(sequenceFeature.end) - 1, + featureColour, start, end, y1); } } - } - } - if (transparency != 1.0f && g != null && transparencyAvailable) + if (transparency != 1.0f && g != null) { Graphics2D g2 = (Graphics2D) g; g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, @@ -409,17 +433,22 @@ public class FeatureRenderer extends } } - boolean transparencyAvailable = true; - - protected void setTransparencyAvailable(boolean isTransparencyAvailable) - { - transparencyAvailable = isTransparencyAvailable; - } - - @Override - public boolean isTransparencyAvailable() + /** + * Answers true if the feature belongs to a feature group which is not + * currently displayed, else false + * + * @param sequenceFeature + * @return + */ + protected boolean featureGroupNotShown( + final SequenceFeature sequenceFeature) { - return transparencyAvailable; + return featureGroups != null + && sequenceFeature.featureGroup != null + && sequenceFeature.featureGroup.length() != 0 + && featureGroups.containsKey(sequenceFeature.featureGroup) + && !featureGroups.get(sequenceFeature.featureGroup) + .booleanValue(); } /** @@ -427,6 +456,7 @@ public class FeatureRenderer extends * discover and display. * */ + @Override public void featuresAdded() { lastSeq = null;