001package org.biojava.bio.gui.sequence; 002 003import java.awt.Graphics; 004import java.awt.Graphics2D; 005 006import javax.swing.JComponent; 007 008import org.biojava.bio.seq.FeatureHolder; 009import org.biojava.bio.symbol.SymbolList; 010 011/** 012 * Renders a sequence as a circle using a CircularRenderer. 013 * 014 * <p> 015 * This component will first transform the graphic coordinates so that 0,0 is at 016 * the centre of the circle. The size of the circle is estimated from the radius 017 * property and the depth of the renderer. 018 * </p> 019 * 020 * <p> 021 * All angles are measured in radians. Some java gui classes use radians and 022 * some use degrees. Be carefull to use the right one. Math has a couple 023 * of methods for conversions. 024 * </p> 025 * 026 * @author Matthew Pocock 027 * @since 1.4 028 */ 029public class CircularRendererPanel 030extends JComponent { 031 private final CircularRendererContext ctxt; 032 033 { 034 ctxt = new CTXT(); 035 } 036 037 private SymbolList symList; 038 private double radius; 039 private CircularRenderer renderer; 040 private double offset; 041 042 public double getRadius() { 043 return radius; 044 } 045 046 public void setRadius(double radius) { 047 this.radius = radius; 048 } 049 050 public SymbolList getSequence() { 051 return symList; 052 } 053 054 public void setSequence(SymbolList symList) { 055 this.symList = symList; 056 } 057 058 public double getOffset() { 059 return offset; 060 } 061 062 public void setOffset(double offset) { 063 this.offset = offset; 064 } 065 066 public CircularRenderer getRenderer() { 067 return renderer; 068 } 069 070 public void setRenderer(CircularRenderer renderer) { 071 this.renderer = renderer; 072 } 073 074 public synchronized void paintComponent(Graphics g) { 075 super.paintComponent(g); 076 if(!isActive()) return; 077 078 double depth = renderer.getDepth(ctxt); 079 080 Graphics2D g2 = (Graphics2D) g; 081 g2.translate((depth + radius), (depth + radius)); 082 083 renderer.paint(g2, ctxt); 084 } 085 086 private boolean isActive() { 087 return renderer != null; 088 } 089 090 private final class CTXT 091 implements CircularRendererContext { 092 public double getOffset() { 093 return offset; 094 } 095 096 public double getAngle(int indx) { 097 return ((double) indx) * 2.0 * Math.PI / ((double) symList.length()) + offset; 098 } 099 100 public int getIndex(double angle) { 101 return (int) ( (angle - offset) * ((double) symList.length()) / (2.0 * Math.PI)); 102 } 103 104 public double getRadius() { 105 return radius; 106 } 107 108 public SymbolList getSymbols() { 109 return symList; 110 } 111 112 public FeatureHolder getFeatures() { 113 if(symList instanceof FeatureHolder) { 114 return (FeatureHolder) symList; 115 } else { 116 return FeatureHolder.EMPTY_FEATURE_HOLDER; 117 } 118 } 119 } 120}