/* * BioJava development code This code may be freely distributed and modified * under the terms of the GNU Lesser General Public Licence. This should be * distributed with the code. If you do not have a copy, see: * http://www.gnu.org/copyleft/lesser.html Copyright for this code is held * jointly by the individual authors. These should be listed in @author doc * comments. For more information on the BioJava project and its aims, or to * join the biojava-l mailing list, visit the home page at: * http://www.biojava.org/ */ package org.biojava.bio.gui.sequence; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import org.biojava.bio.gui.glyph.ArrowGlyph; import org.biojava.bio.gui.glyph.Glyph; import org.biojava.bio.seq.Feature; import org.biojava.bio.seq.FeatureFilter; import org.biojava.bio.seq.FeatureHolder; import org.biojava.bio.seq.StrandedFeature; import org.biojava.utils.ChangeVetoException; /** * A FeatureRenderer that renders a particular Glyph for Features accepted by a * particular FeatureFilter * * @author Mark Southern * @author Andreas Dräger * @see org.biojava.bio.gui.glyph.Glyph * @since 1.5 */ public class GlyphFeatureRenderer extends FilteringRenderer implements FeatureRenderer { /** * */ private static final long serialVersionUID = 7005846487574725181L; private double depth = 15; protected List fList; protected List gList; public GlyphFeatureRenderer() { super(); fList = new ArrayList(); gList = new ArrayList(); } public void addFilterAndGlyph(FeatureFilter ff, Glyph g) throws ChangeVetoException { if (!fList.contains(ff)) { fList.add(ff); gList.add(g); if (fList.size() == 0) setFilter(FeatureFilter.none); else { FeatureFilter f = fList.get(0); if (fList.size() > 1) for (int i = 1; i < fList.size(); i++) f = new FeatureFilter.Or(f, fList.get(i)); setFilter(f); } } } public void removeFilterWithGlyph(FeatureFilter ff) throws ChangeVetoException { if (fList.contains(ff)) { gList.remove(fList.indexOf(ff)); fList.remove(ff); if (fList.size() == 0) { setFilter(FeatureFilter.none); } else { FeatureFilter f = fList.get(0); if (fList.size() > 1) for (int i = 1; i < fList.size(); i++) f = new FeatureFilter.Or(f, fList.get(i)); setFilter(f); } } } /** * Returns the ith {@link FeatureFilter} in this renderer. * * @param i * @return the featureFilter */ public FeatureFilter getFeatureFilter(int i) { return fList.get(i); } /** * Returns true if the given {@link FeatureFilter} is already contained in this * renderer. * * @param ff * @return flag if featurefilter is contained */ public boolean containsFilter(FeatureFilter ff) { return fList.contains(ff); } /** * Allows setting another {@link Glyph } object to be painted for the given * FeatureFilter. * * @param ff * @param glyph * @throws ChangeVetoException */ public void setGlyphForFilter(FeatureFilter ff, Glyph glyph) throws NoSuchElementException { if (fList.contains(ff)) gList.set(fList.indexOf(ff), glyph); else throw new NoSuchElementException(ff.toString()); } /** * Returns the {@link Glyph} object which is assigned to the given feature * filter. * * @param ff * @return {@link Glyph} object * @throws NoSuchElementException */ public Glyph getGlyphForFilter(FeatureFilter ff) throws NoSuchElementException { if (fList.contains(ff)) return gList.get(fList.indexOf(ff)); throw new NoSuchElementException(ff.toString()); } public void setDepth(double depth) { this.depth = depth; } /** * Returns the depth property of this class. * * @return the depth */ public double getDepth(SequenceRenderContext src) { return depth; } public FeatureHolder processMouseEvent(FeatureHolder fh, SequenceRenderContext src, MouseEvent me) { return fh; } public void renderFeature(Graphics2D g2, Feature f, SequenceRenderContext src) { float minBounds = (float) src.sequenceToGraphics(f.getLocation().getMin()); float maxBounds = (float) src .sequenceToGraphics(f.getLocation().getMax() + 1); Rectangle2D.Float bounds; bounds = new Rectangle2D.Float(minBounds, 0, maxBounds - minBounds, (float) depth); for (int i = 0; i < fList.size(); i++) if (fList.get(i).accept(f)) { Glyph g = gList.get(i); g.setBounds(bounds); if ((g instanceof ArrowGlyph) && (f instanceof StrandedFeature)) ((ArrowGlyph) g).setDirection(((StrandedFeature) f).getStrand() .getValue()); if (src.getDirection() == SequenceRenderContext.HORIZONTAL) g.render(g2); } } }