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.awt.geom.AffineTransform; 027import java.util.List; 028 029import org.biojava.utils.AssertionFailure; 030import org.biojava.utils.ChangeEvent; 031import org.biojava.utils.ChangeSupport; 032import org.biojava.utils.ChangeType; 033import org.biojava.utils.ChangeVetoException; 034 035/** 036 * A renderer that adds padding before and after a delegate renderer. 037 * 038 * @author Matthew Pocock 039 * @since 1.2 040 */ 041public class PaddingRenderer 042extends SequenceRendererWrapper { 043 /** 044 * Event type for when the size of the padding changes. 045 */ 046 public static ChangeType PADDING = new ChangeType( 047 "The padding has changed", 048 "org.biojava.bio.gui.sequence.PaddingRenderer", 049 "PADDING", 050 SequenceRenderContext.LAYOUT 051 ); 052 053 private double padding; 054 055 protected boolean hasListeners() { 056 return super.hasListeners(); 057 } 058 059 protected ChangeSupport getChangeSupport(ChangeType ct) { 060 return super.getChangeSupport(ct); 061 } 062 063 /** 064 * Build a new PaddingRenderer with zero padding. 065 * <p> 066 * This will cause a rendering effect equivalent to missing out the padding 067 * renderer all together. 068 */ 069 public PaddingRenderer() { 070 padding = 0.0; 071 } 072 073 /** 074 * Build a new PaddingRenderer that wraps <code>renderer</code> and has 075 * padding depth <code>padding</code>. 076 * 077 * @param renderer the SequenceRenderer that will actually do the rendering 078 * @param padding the number of pixels to leave both before and after 079 * rendering the child renderer 080 */ 081 public PaddingRenderer( 082 SequenceRenderer renderer, 083 double padding 084 ) { 085 super(renderer); 086 try { 087 setPadding(padding); 088 } catch (ChangeVetoException cve) { 089 throw new AssertionFailure("Assertion Failure: Should have no listeners", cve); 090 } 091 } 092 093 /** 094 * Set the padding. 095 * <p> 096 * The padding will be added to the area before and after that required to 097 * render the delegate renderer. 098 * 099 * @param padding the new padding size 100 * @throws ChangeVetoException if padding is negative or if any listener 101 * objected to the change 102 */ 103 public void setPadding(double padding) 104 throws ChangeVetoException { 105 if(padding < 0.0) { 106 ChangeEvent ce = new ChangeEvent( 107 this, PADDING, new Double(this.padding), new Double(padding) 108 ); 109 throw new ChangeVetoException( 110 ce, 111 "Can't set padding to a negative value" 112 ); 113 } 114 if(hasListeners()) { 115 ChangeSupport cs = getChangeSupport(PADDING); 116 synchronized(cs) { 117 ChangeEvent ce = new ChangeEvent( 118 this, PADDING, new Double(this.padding), new Double(padding) 119 ); 120 cs.firePreChangeEvent(ce); 121 this.padding = padding; 122 cs.firePostChangeEvent(ce); 123 } 124 } else { 125 this.padding = padding; 126 } 127 } 128 129 /** 130 * Retrieve the current padding. 131 * 132 * @return the current padding 133 */ 134 public double getPadding() { 135 return this.padding; 136 } 137 138 public double getDepth(SequenceRenderContext src) { 139 return super.getDepth(src) + padding * 2.0; 140 } 141 142 public double getMinimumLeader(SequenceRenderContext src) { 143 return super.getMinimumLeader(src); 144 } 145 146 public double getMinimumTrailer(SequenceRenderContext src) { 147 return super.getMinimumTrailer(src); 148 } 149 150 public void paint( 151 Graphics2D g, 152 SequenceRenderContext src 153 ) { 154 AffineTransform old = g.getTransform(); 155 if(src.getDirection() == SequenceRenderContext.HORIZONTAL) { 156 g.translate(0.0, getPadding()); 157 } else { 158 g.translate(getPadding(), 0.0); 159 } 160 super.paint(g, src); 161 g.setTransform(old); 162 } 163 164 public SequenceViewerEvent processMouseEvent( 165 SequenceRenderContext src, 166 MouseEvent me, 167 List path 168 ) { 169 int padding = (int) getPadding(); 170 if(src.getDirection() == SequenceRenderContext.HORIZONTAL) { 171 me.translatePoint(0, -padding); 172 } else { 173 me.translatePoint(-padding, 0); 174 } 175 SequenceViewerEvent sve = super.processMouseEvent( 176 src, 177 me, 178 path 179 ); 180 if(src.getDirection() == SequenceRenderContext.HORIZONTAL) { 181 me.translatePoint(0, padding); 182 } else { 183 me.translatePoint(padding, 0); 184 } 185 return sve; 186 } 187 188 public String toString() { 189 return "PaddingRenderer(" + getRenderer().toString() + ")"; 190 } 191}