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.Font;
025import java.awt.Graphics2D;
026import java.awt.Shape;
027import java.awt.font.FontRenderContext;
028import java.awt.font.GlyphVector;
029import java.awt.geom.AffineTransform;
030
031import org.biojava.utils.AbstractChangeable;
032import org.biojava.utils.ChangeEvent;
033import org.biojava.utils.ChangeSupport;
034import org.biojava.utils.ChangeType;
035import org.biojava.utils.ChangeVetoException;
036
037/**
038 * @author Matthew Pocock
039 */
040public class SimpleLabelRenderer
041extends AbstractChangeable
042implements LabelRenderer{
043  public static final ChangeType LABEL = new ChangeType(
044    "The label has changed",
045    "org.biojava.bio.gui.sequence.SimpleLabelRenderer",
046    "LABEL",
047    SequenceRenderContext.LAYOUT
048  );
049
050  private static final AffineTransform FLIP =
051    new AffineTransform(0.0, 1.0, -1.0, 0.0, 0.0, 0.0);
052  private String label;
053  private Shape labelGlyphH;
054  private Shape labelGlyphV;
055
056  protected Shape getLabelGlyph(
057        SequenceRenderContext src,
058        FontRenderContext frc
059  ) {
060    Shape s;
061
062    if (src.getDirection() == SequenceRenderContext.HORIZONTAL) {
063      if(labelGlyphH == null) {
064        Font font = src.getFont();
065        labelGlyphH = font.createGlyphVector(frc, label).getOutline();
066      }
067      s = labelGlyphH;
068    } else {
069      if(labelGlyphV == null) {
070        Font font = src.getFont().deriveFont(FLIP);
071        labelGlyphV = font.createGlyphVector(frc, label).getOutline();
072      }
073      s = labelGlyphV;
074    }
075
076    return s;
077  }
078
079  public void setLabel(String label)
080  throws ChangeVetoException {
081    if(hasListeners()) {
082      ChangeSupport cs = getChangeSupport(LABEL);
083      synchronized(cs) {
084        ChangeEvent ce = new ChangeEvent(
085          this, SequenceRenderContext.LAYOUT, null, null, new ChangeEvent(
086            this, LABEL, this.label, label
087          )
088        );
089        cs.firePreChangeEvent(ce);
090        this.label = label;
091        this.labelGlyphH = null;
092        this.labelGlyphV = null;
093        cs.firePostChangeEvent(ce);
094      }
095    } else {
096      this.label = label;
097      this.labelGlyphH = null;
098      this.labelGlyphV = null;
099    }
100  }
101
102  public String getLabel() {
103    return label;
104  }
105
106  public double getMinimumWidth(SequenceRenderContext sp) {
107    if(label == null) {
108      return 0.0;
109    }
110    Font f = sp.getFont();
111    FontRenderContext frc = new FontRenderContext(null, true, true);
112    GlyphVector gv = f.createGlyphVector(frc, label);
113    return gv.getVisualBounds().getWidth();
114  }
115
116  public void paint(
117    Graphics2D g, SequenceRenderContext sp,
118    int min, int max, SequenceRenderContext.Border side
119  ) {
120/*    if(label != null) {
121      Rectangle2D.Double labelBox = null;
122      Shape labelGlyph = getLabelGlyph(sp, g.getFontRenderContext());
123      if (sp.getDirection() == sp.HORIZONTAL) {
124        labelBox = new Rectangle2D.Double(
125          0, 0,
126          leading.getSize(), getDepth()
127        );
128      } else {
129        labelBox = new Rectangle2D.Double(
130          seqBox.getMinX(), seqBox.getMinY() - side.getSize(),
131          seqBox.getWidth(), side.getSize()
132        );
133      }
134      renderLabel(g, labelGlyph, labelBox, sp, side);
135    }*/
136  }
137/*
138  private void renderLabel(
139      Graphics2D g,
140      Shape gv, Rectangle2D labelBox,
141      SequenceRenderContext sp, SequenceRenderContext.Border border
142    ) {
143      Rectangle2D bounds = gv.getBounds2D();
144      double along = 0.0;
145      double across = 0.0;
146      if (sp.getDirection() == SequenceRenderContext.HORIZONTAL) {
147        across = labelBox.getCenterY() - bounds.getCenterY();
148        int balign = border.getAlignment();
149
150        if (balign == SequenceRenderContext.Border.LEADING)
151            along = labelBox.getMinX() - bounds.getMinX();
152        else if (balign == SequenceRenderContext.Border.TRAILING)
153            along = labelBox.getMaxX() - bounds.getMaxX();
154        else if (balign == SequenceRenderContext.Border.CENTER)
155            along = labelBox.getCenterX() - bounds.getCenterX();
156
157        AffineTransform at = g.getTransform();
158        g.translate(along, across);
159        g.fill(gv);
160        g.draw(gv);
161        g.setTransform(at);
162      } else {
163        across = labelBox.getCenterX() - bounds.getCenterX();
164        int balign = border.getAlignment();
165
166        if (balign == SequenceRenderContext.Border.LEADING)
167            along = labelBox.getMinY() - bounds.getMinY();
168        else if (balign == SequenceRenderContext.Border.TRAILING)
169            along = labelBox.getMaxY() - bounds.getMaxY();
170        else if (balign == SequenceRenderContext.Border.CENTER)
171            along = labelBox.getCenterY() - bounds.getCenterY();
172
173        AffineTransform at = g.getTransform();
174        g.translate(across, along);
175        g.fill(gv);
176        g.draw(gv);
177        g.setTransform(at);
178      }
179    }*/
180}