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.Paint; 026import java.awt.Stroke; 027import java.awt.geom.RoundRectangle2D; 028 029import org.biojava.bio.seq.Feature; 030import org.biojava.bio.symbol.Location; 031 032/** 033 * <code>RoundRectangularBeadRenderer</code> renders features 034 * as rectangles with rounded corners. Their outline and fill 035 * <code>Paint</code>, <code>Stroke</code>, feature depth, Y-axis 036 * displacement are configurable. 037 * 038 * @author Keith James 039 * @since 1.2 040 */ 041public class RoundRectangularBeadRenderer extends AbstractBeadRenderer 042{ 043 protected RoundRectangle2D rect; 044 protected double arcWidth; 045 protected double arcHeight; 046 047 /** 048 * Creates a new <code>RoundRectangularBeadRenderer</code> 049 * object with the default settings. 050 */ 051 public RoundRectangularBeadRenderer() 052 { 053 super(); 054 rect = new RoundRectangle2D.Double(); 055 arcWidth = 5.0; 056 arcHeight = 5.0; 057 } 058 059 /** 060 * Creates a new <code>RoundRectangularBeadRenderer</code>. 061 * 062 * @param beadDepth a <code>double</code>. 063 * @param beadDisplacement a <code>double</code>. 064 * @param beadOutline a <code>Paint</code>. 065 * @param beadFill a <code>Paint</code>. 066 * @param beadStroke a <code>Stroke</code>. 067 * @param arcWidth a <code>double</code> value which sets the arc 068 * width of the corners. 069 * @param arcHeight a <code>double</code> value which sets the arc 070 * height of the corners. 071 */ 072 public RoundRectangularBeadRenderer(double beadDepth, 073 double beadDisplacement, 074 Paint beadOutline, 075 Paint beadFill, 076 Stroke beadStroke, 077 double arcWidth, 078 double arcHeight) 079 { 080 super(beadDepth, beadDisplacement, beadOutline, beadFill, beadStroke); 081 rect = new RoundRectangle2D.Double(); 082 this.arcWidth = arcWidth; 083 this.arcHeight = arcHeight; 084 } 085 086 /** 087 * <code>renderBead</code> renders features as a rectangle with 088 * rounded corners. 089 * 090 * @param g2 a <code>Graphics2D</code>. 091 * @param f a <code>Feature</code> to render. 092 * @param context a <code>SequenceRenderContext</code> context. 093 */ 094 public void renderBead(Graphics2D g2, 095 Feature f, 096 SequenceRenderContext context) 097 { 098 Location loc = f.getLocation(); 099 100 int min = loc.getMin(); 101 int max = loc.getMax(); 102 int dif = max - min; 103 104 if (context.getDirection() == SequenceRenderContext.HORIZONTAL) 105 { 106 double posXW = context.sequenceToGraphics(min); 107 double posYN = beadDisplacement; 108 double width = Math.max(((double) (dif + 1)) * context.getScale(), 1.0); 109 double height = Math.min(beadDepth, width / 2.0); 110 111 // If the bead height occupies less than the full height 112 // of the renderer, move it down so that it is central 113 if (height < beadDepth) 114 posYN += ((beadDepth - height) / 2.0); 115 116 rect.setRoundRect(posXW, posYN, 117 Math.floor(width), 118 Math.floor(height), 119 arcWidth, arcHeight); 120 } 121 else 122 { 123 double posXW = beadDisplacement; 124 double posYN = context.sequenceToGraphics(min); 125 double height = Math.max(((double) dif + 1) * context.getScale(), 1.0); 126 double width = Math.min(beadDepth, height / 2.0); 127 128 if (width < beadDepth) 129 posXW += ((beadDepth - width) / 2.0); 130 131 rect.setRoundRect(posXW, posYN, 132 Math.floor(width), 133 Math.floor(height), 134 arcWidth, arcHeight); 135 } 136 137 g2.setPaint(beadFill); 138 g2.fill(rect); 139 140 g2.setStroke(beadStroke); 141 g2.setPaint(beadOutline); 142 g2.draw(rect); 143 } 144 145 /** 146 * <code>getDepth</code> calculates the depth required by this 147 * renderer to display its beads. 148 * 149 * @param context a <code>SequenceRenderContext</code>. 150 * 151 * @return a <code>double</code>. 152 */ 153 public double getDepth(SequenceRenderContext context) 154 { 155 // Get max depth of delegates using base class method 156 double maxDepth = super.getDepth(context); 157 return Math.max(maxDepth, (beadDepth + beadDisplacement)); 158 } 159}