001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022package org.biojava.bio.gui.sequence;
023
024import java.awt.Color;
025import java.awt.Graphics2D;
026import java.awt.event.MouseEvent;
027import java.awt.font.FontRenderContext;
028import java.awt.geom.AffineTransform;
029
030import org.biojava.bio.Annotation;
031import org.biojava.bio.BioError;
032import org.biojava.bio.seq.Feature;
033import org.biojava.bio.seq.FeatureHolder;
034import org.biojava.bio.symbol.Location;
035import org.biojava.utils.AbstractChangeable;
036import org.biojava.utils.ChangeEvent;
037import org.biojava.utils.ChangeSupport;
038import org.biojava.utils.ChangeType;
039import org.biojava.utils.ChangeVetoException;
040
041/**
042 * @author unknown
043 * @author Matthew Pocock
044 */
045public class FeatureLabelRenderer
046extends AbstractChangeable
047implements FeatureRenderer {
048  public static final ChangeType LABEL_MAKER = new ChangeType(
049    "The label maker has changed",
050    "org.biojava.bio.gui.sequence.FeatureLabelRenderer",
051    "LABEL_MAKER",
052    SequenceRenderContext.REPAINT
053  );
054
055  private static FontRenderContext FRC = new FontRenderContext(
056    new AffineTransform(),
057    false,
058    true
059  );
060
061  private LabelMaker labelMaker;
062
063  public FeatureLabelRenderer() {}
064
065  public FeatureLabelRenderer(LabelMaker labelMaker) {
066    try {
067      setLabelMaker(labelMaker);
068    } catch (ChangeVetoException cve) {
069      throw new BioError("Assertion Failure: could not set label maker",cve);
070    }
071  }
072
073  public LabelMaker getLabelMaker() {
074    return this.labelMaker;
075  }
076
077  public void setLabelMaker(LabelMaker labelMaker)
078  throws ChangeVetoException {
079    if(hasListeners()) {
080      ChangeSupport cs = getChangeSupport(LABEL_MAKER);
081      ChangeEvent ce = new ChangeEvent(
082        this, LABEL_MAKER,
083        labelMaker, this.labelMaker
084      );
085      synchronized(cs) {
086        cs.firePreChangeEvent(ce);
087        this.labelMaker = labelMaker;
088        cs.firePostChangeEvent(ce);
089      }
090    } else {
091      this.labelMaker = labelMaker;
092    }
093  }
094
095  public double getDepth(SequenceRenderContext src) {
096    return src.getFont().getMaxCharBounds(FRC).getHeight();
097  }
098
099  public double getMinimumLeader(SequenceRenderContext src) {
100    return 0.0;
101  }
102
103  public double getMinimumTrailer(SequenceRenderContext src) {
104    return 0.0;
105  }
106
107  public void renderFeature(
108    Graphics2D g,
109    Feature feat,
110    SequenceRenderContext src
111  ) {
112    Location loc = feat.getLocation();
113    String label = labelMaker.makeLabel(feat);
114
115    g.setPaint(Color.black);
116    int min = Math.max(loc.getMin(), src.getRange().getMin());
117    int max = Math.min(loc.getMax(), src.getRange().getMax());
118    int mid = (min + max) / 2;
119
120    g.drawString(
121      label,
122      (float) (src.sequenceToGraphics(mid)),
123      (float) (getDepth(src) - 2.0)
124    );
125  }
126
127  public FeatureHolder processMouseEvent(
128    FeatureHolder hits,
129    SequenceRenderContext src,
130    MouseEvent me
131  ) {
132    return hits;
133  }
134
135  public static interface LabelMaker {
136    String makeLabel(Feature f);
137  }
138
139  public static class SourceLabelMaker
140  implements LabelMaker {
141    public String makeLabel(Feature f) {
142      return f.getSource();
143    }
144  }
145
146  public static class TypeLabelMaker
147  implements LabelMaker {
148    public String makeLabel(Feature f) {
149      return f.getType();
150    }
151  }
152
153  public static class AnnotationLabelMaker
154  implements LabelMaker {
155    private Object key;
156
157    public AnnotationLabelMaker() {
158    }
159
160    public AnnotationLabelMaker(Object key) {
161      setKey(key);
162    }
163
164    public void setKey(Object key) {
165      this.key = key;
166    }
167
168    public Object getKey() {
169      return key;
170    }
171
172    public String makeLabel(Feature feat) {
173      Annotation ann = feat.getAnnotation();
174      if(ann.containsProperty(key)) {
175        return ann.getProperty(key).toString();
176      } else {
177        return "";
178      }
179    }
180  }
181}