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.Graphics2D;
025import java.awt.event.MouseEvent;
026import java.util.List;
027
028import org.biojava.utils.ChangeEvent;
029import org.biojava.utils.ChangeForwarder;
030import org.biojava.utils.ChangeSupport;
031import org.biojava.utils.ChangeType;
032
033/**
034 * The interface for things that can render a line of information about a
035 * sequence.
036 * <p>
037 * Renderers are always activated within the context of a particular sequence
038 * panel. A single Renderer can be shared among many sequence panels, or added
039 * multiple times to the same panel. The renderer is required to request how
040 * much leading and trailing space it requires, as well as the depth (space
041 * orthogonal to the direction in which the sequence is rendered).
042 * <p>
043 * The leading and trailing distances are the number of pixels overhang needed
044 * to cleanly render any line of sequence information. For example, a ruler will
045 * need trailing space to render the total sequence length at the end.
046 *
047 * @author Thomas Down
048 * @author Matthew Pocock
049 * @author Keith James
050 */
051public interface SequenceRenderer {
052  
053  /**
054   * Render a portion (possibly all) of the information for src to g, displaying
055   * all of the data that would fall within seqBox.
056   *
057   * @param g the Graphics2D to render to
058   * @param src the SequenceRenderContext that encapsulates the information to render
059   */
060  void paint(Graphics2D g, SequenceRenderContext src);
061  
062  /**
063   * Retrieve the depth of this renderer when rendering src.
064   * <p>
065   * The depth may vary between sequence panels - for example based upon
066   * sequence length. Each line of information in the SequenceRendererContext
067   * only renders a region of the sequence. The depth for one complete line may
068   * be different from that for another due to the sequence having more or less
069   * information in that region to show. For example, a feature renderer
070   * implementation may chose to collapse down to a depth of zero pixels if
071   * there are no features to render within a region.
072   *
073   * @param src the SequenceRenderContext to return info for
074   * @return the depth of the renderer for that sequence panel
075   */
076  double getDepth(SequenceRenderContext src);
077
078  /**
079   * Retrieve the minimum leading distance for this renderer when rendering src.
080   * <p>
081   * The leading distance may vary between sequence panels - for example based
082   * upon sequence length.
083   *
084   * @param src the SequenceRenderContext to return info for
085   * @return the leading distance of the renderer for that sequence panel
086   */
087  double getMinimumLeader(SequenceRenderContext src);
088    
089  /**
090   * Retrieve the minimum trailing distance for this renderer when rendering src.
091   * <p>
092   * The trailing distance may vary between sequence panels - for example based
093   * upon sequence length.
094   *
095   * @param src the SequenceRenderContext to return info for
096   * @return the trailing distance of the renderer for that sequence panel
097   */
098  double getMinimumTrailer(SequenceRenderContext src);
099  
100  /**
101   * Produce a SequenceViewerEvent in response to a mouse gesture.
102   * <p>
103   * A SequenceRenderer that performs any form of coordinate remapping should
104   * ensure that it appropriately transforms the mouse event. However, in the
105   * SequenceViewerEvent returned, the MouseEvent should be in untransformed
106   * coordinates.
107   * <p>
108   * The SequenceRenderer implementation should append itself to the path list
109   * before constructing the SequenceViewerEvent.
110   *
111   * @param src the SequenceRenderContext currently in scope
112   * @param me  a MouseEvent that caused this request
113   * @param path the List of SequenceRenderer instances passed through so far
114   * @return a SequenceViewerEvent encapsulating the mouse gesture
115   *
116   * @since 1.2
117   */
118  SequenceViewerEvent processMouseEvent(
119    SequenceRenderContext src,
120    MouseEvent me,
121    List path
122  );
123  
124  public static class RendererForwarder extends ChangeForwarder {
125    public RendererForwarder(SequenceRenderer source, ChangeSupport cs) {
126      super(source, cs);
127    }
128    
129    public ChangeEvent generateEvent(ChangeEvent ce) {
130      ChangeType cType = ce.getType();
131      ChangeType newType;
132      if(cType.isMatchingType(SequenceRenderContext.LAYOUT)) {
133        newType = SequenceRenderContext.LAYOUT;
134      } else if(cType.isMatchingType(SequenceRenderContext.REPAINT)) {
135        newType = SequenceRenderContext.REPAINT;
136      } else {
137        return null;
138      }
139      return new ChangeEvent(getSource(), newType, null, null, ce);
140    }
141  }
142}