001package org.biojava.bio.gui.sequence;
002
003import java.awt.Graphics2D;
004import java.util.Iterator;
005
006import org.biojava.bio.seq.FeatureHolder;
007import org.biojava.bio.symbol.GappedSymbolList;
008import org.biojava.bio.symbol.Location;
009import org.biojava.bio.symbol.RangeLocation;
010import org.biojava.bio.symbol.SymbolList;
011
012/**
013 * A renderer that will display a gapped sequence as a discontinuous series of
014 * regions.
015 *
016 * <p>
017 * Each ungapped block in the gapped symbol list will be displayed as a
018 * contiguous region by this renderer. Where there are gaps, this renderer
019 * will display nothing. Then, when the gaps are over, it will continue to
020 * render the ungapped sequence. This has the effect of snapping the image
021 * of the ungapped sequence where there are gaps, so as to allow it to be
022 * viewed in the gapped co-ordinate system.
023 * </p>
024 *
025 * @author Matthew Pocock
026 */
027public class GappedRenderer
028extends SequenceRendererWrapper {
029  public GappedRenderer() {
030    super();
031  }
032
033  public GappedRenderer(SequenceRenderer renderer) {
034    super(renderer);
035  }
036
037  public double getDepth(SequenceRenderContext src) {
038    if(src.getSymbols() instanceof GappedSymbolList) {
039      GappedSymbolList gsym = (GappedSymbolList) src.getSymbols();
040      Location ungapped = gsym.getUngappedLocation();
041      double depth = 0.0;
042
043      Iterator bi = ungapped.blockIterator();
044      while(bi.hasNext()) {
045        RangeLocation loc = (RangeLocation) bi.next();
046        depth = Math.max(depth, super.getDepth(makeContext(src, loc)));
047      }
048
049      return depth;
050    } else {
051      return super.getDepth(src);
052    }
053  }
054
055  public double getMinimumLeader(SequenceRenderContext src) {
056    if(src.getSymbols() instanceof GappedSymbolList) {
057      GappedSymbolList gsym = (GappedSymbolList) src.getSymbols();
058      Location ungapped = gsym.getUngappedLocation();
059      Iterator bi = ungapped.blockIterator();
060      if(bi.hasNext()) {
061        return super.getMinimumLeader(
062              makeContext(src, (RangeLocation) bi.next()));
063      } else {
064        return 0.0;
065      }
066    } else {
067      return super.getMinimumLeader(src);
068    }
069  }
070
071  public double getMinimumTrailer(SequenceRenderContext src) {
072    if(src.getSymbols() instanceof GappedSymbolList) {
073      GappedSymbolList gsym = (GappedSymbolList) src.getSymbols();
074      Location ungapped = gsym.getUngappedLocation();
075      Iterator bi = ungapped.blockIterator();
076      RangeLocation loc = null;
077      while(bi.hasNext()) {
078        loc = (RangeLocation) bi.next();
079      }
080      if(loc == null) {
081        return 0.0;
082      } else {
083        return super.getMinimumTrailer(makeContext(src, loc));
084      }
085    } else {
086      return super.getMinimumTrailer(src);
087    }
088  }
089
090  public void paint(
091          Graphics2D g,
092          SequenceRenderContext src
093          ) {
094    if(src.getSymbols() instanceof GappedSymbolList) {
095      GappedSymbolList gsym = (GappedSymbolList) src.getSymbols();
096      Location ungapped = gsym.getUngappedLocation();
097      Iterator bi = ungapped.blockIterator();
098      while(bi.hasNext()) {
099        RangeLocation loc = (RangeLocation) bi.next();
100        super.paint(g, makeContext(src, loc));
101      }
102    } else {
103      super.paint(g, src);
104    }
105  }
106
107  protected SequenceRenderContext makeContext(SequenceRenderContext src,
108          RangeLocation loc) {
109    GappedSymbolList gsl = (GappedSymbolList) src.getSymbols();
110    RangeLocation sourceLoc = new RangeLocation(
111            gsl.viewToSource(loc.getMin()),
112            gsl.viewToSource(loc.getMax())
113    );
114    int trans = loc.getMin() - sourceLoc.getMin();
115    SymbolList ugsl = gsl.getSourceSymbolList();
116
117    return new SubSequenceRenderContext(
118            src,
119            ugsl,
120            (ugsl instanceof FeatureHolder) ? (FeatureHolder) ugsl : null,
121            sourceLoc,
122            trans);
123  }
124}