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 */ 021package org.biojava.bio.gui.sequence; 022 023import java.awt.Color; 024import java.awt.Font; 025import java.awt.Graphics; 026import java.util.ArrayList; 027import java.util.Iterator; 028import java.util.List; 029 030import javax.swing.BoxLayout; 031import javax.swing.JPanel; 032 033import org.biojava.bio.gui.sequence.tracklayout.SimpleTrackLayout; 034import org.biojava.bio.gui.sequence.tracklayout.TrackLayout; 035import org.biojava.bio.seq.Sequence; 036import org.biojava.bio.symbol.RangeLocation; 037import org.biojava.utils.ChangeVetoException; 038 039/** 040 * Handles multiple SequencePanels and Ranges so that a Sequence can be wrapped 041 * over more than one line on screen. This is particularly useful for viewing 042 * Protein sequences that would be viewed at a single residue resolution. 043 * 044 * The interface is very similar to that of the SequencePanels that it wraps 045 * 046 * @author Mark Southern 047 * @see SequencePanel 048 * @since 1.5 049 */ 050public class SequencePanelWrapper extends JPanel { 051 052 /** 053 * Generated Serial Version UID 054 */ 055 private static final long serialVersionUID = 8749249181471157230L; 056 protected SequencePanel[] seqPanels = new SequencePanel[0]; 057 private RangeLocation range; 058 private Sequence sequence; 059 private SequenceRenderer renderer; 060 private double scale = 14.0; 061 private java.awt.RenderingHints hints; 062 private int direction = SequencePanel.HORIZONTAL; 063 private TrackLayout trackLayout = new SimpleTrackLayout(); 064 private List<SequenceViewerListener> viewerListeners = new ArrayList<SequenceViewerListener>(); 065 private List<SequenceViewerMotionListener> motionListeners = new ArrayList<SequenceViewerMotionListener>(); 066 067 /** 068 * Creates a new instance of WrappedSequencePanel 069 */ 070 public SequencePanelWrapper() { 071 initComponents(); 072 } 073 074 protected void initComponents() { 075 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 076 setBackground(Color.WHITE); 077 } 078 079 /* 080 * Sets the track (line) layout strategy. Layouts include a simple wrapping 081 * at a given number of residues and user-defined layouts that can contain 082 * arbitrary length rows. 083 */ 084 public void setTrackLayout(TrackLayout tl) { 085 this.trackLayout = tl; 086 trackLayout.setSequence(getSequence()); 087 trackLayout.setRange(getRange()); 088 089 if (isActive()) { 090 refreshSequencePanels(); 091 } 092 } 093 094 public TrackLayout getTrackLayout() { 095 return this.trackLayout; 096 } 097 098 protected boolean isActive() { 099 return (sequence != null) && (renderer != null) && (range != null); 100 } 101 102 public void setScale(double scale) { 103 this.scale = scale; 104 105 for (int i = 0; i < seqPanels.length; i++) { 106 seqPanels[i].setScale(scale); 107 } 108 } 109 110 public double getScale() { 111 return scale; 112 } 113 114 public void setDirection(int direction) { 115 this.direction = direction; 116 117 for (int i = 0; i < seqPanels.length; i++) { 118 seqPanels[i].setDirection(direction); 119 } 120 121 if (isActive()) { 122 refreshSequencePanels(); 123 } 124 } 125 126 public int getDirection() { 127 return direction; 128 } 129 130 /* 131 * a convenience method. The wrap is passed through to the TrackLayout 132 * implementation. 133 */ 134 public synchronized void setWrap(int w) { 135 trackLayout.setWrap(w); 136 137 if (!isActive()) { 138 return; 139 } 140 141 refreshSequencePanels(); 142 } 143 144 public int getWrap() { 145 return trackLayout.getWrap(); 146 } 147 148 public void setRenderingHints(java.awt.RenderingHints hints) { 149 this.hints = hints; 150 151 for (int i = 0; i < seqPanels.length; i++) { 152 seqPanels[i].setRenderingHints(hints); 153 } 154 } 155 156 public java.awt.RenderingHints getRenderingHints() { 157 return hints; 158 } 159 160 public void setRenderer(SequenceRenderer renderer) { 161 this.renderer = renderer; 162 163 for (int i = 0; i < seqPanels.length; i++) { 164 try { 165 seqPanels[i].setRenderer(renderer); 166 } catch (ChangeVetoException e) { 167 // should never get here 168 e.printStackTrace(); 169 } 170 } 171 } 172 173 public SequenceRenderer getRenderer() { 174 return renderer; 175 } 176 177 public void setSequence(Sequence seq) { 178 if (seq == null) { 179 removeSeqPanels(); 180 181 return; 182 } 183 184 trackLayout.setSequence(sequence = seq); 185 trackLayout.setRange(range = new RangeLocation(1, seq.length())); 186 refreshSequencePanels(); 187 } 188 189 public Sequence getSequence() { 190 return sequence; 191 } 192 193 public void setRange(RangeLocation loc) { 194 trackLayout.setRange(range = loc); 195 refreshSequencePanels(); 196 } 197 198 public RangeLocation getRange() { 199 return range; 200 } 201 202 private void removeSeqPanels() { 203 for (int i = 0; i < seqPanels.length; i++) { 204 remove(seqPanels[i]); 205 } 206 207 setSize(0, 0); // make sure view is refreshed properly 208 setLayout(null); 209 revalidate(); 210 } 211 212 public void resizeAndValidate() { 213 for (int i = 0; i < seqPanels.length; i++) { 214 seqPanels[i].resizeAndValidate(); 215 } 216 } 217 218 protected void refreshSequencePanels() { 219 removeSeqPanels(); 220 221 RangeLocation[] ranges = trackLayout.getRanges(); 222 seqPanels = new SequencePanel[ranges.length]; 223 224 if (getDirection() == SequencePanel.HORIZONTAL) { 225 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 226 } else { 227 setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); 228 } 229 230 for (int i = 0; i < ranges.length; i++) { 231 // logger.debug("Setting sequence panel " + i); 232 seqPanels[i] = new SequencePanel(); 233 seqPanels[i].setFont(getFont()); 234 seqPanels[i].setAlignmentX(LEFT_ALIGNMENT); 235 seqPanels[i].setAlignmentY(TOP_ALIGNMENT); 236 seqPanels[i].setSequence(getSequence()); 237 238 // seqPanels[i].setRange( ranges[i] ); 239 // bug in biojava-1.4pre1 - add +1 to max range 240 seqPanels[i].setRange(new RangeLocation(ranges[i].getMin(), 241 ranges[i].getMax() + 1)); 242 seqPanels[i].setDirection(getDirection()); 243 seqPanels[i].setScale(getScale()); 244 245 for (Iterator<SequenceViewerListener> it = viewerListeners 246 .iterator(); it.hasNext();) { 247 seqPanels[i].addSequenceViewerListener(it.next()); 248 } 249 250 for (Iterator<SequenceViewerMotionListener> jt = motionListeners 251 .iterator(); jt.hasNext();) { 252 seqPanels[i].addSequenceViewerMotionListener(jt.next()); 253 } 254 255 add(seqPanels[i]); 256 } 257 258 setRenderer(getRenderer()); 259 } 260 261 public void addSequenceViewerListener(SequenceViewerListener l) { 262 viewerListeners.add(l); 263 264 for (int i = 0; i < seqPanels.length; i++) { 265 seqPanels[i].addSequenceViewerListener(l); 266 } 267 } 268 269 public void removeSequenceViewerListener(SequenceViewerListener l) { 270 viewerListeners.remove(l); 271 272 for (int i = 0; i < seqPanels.length; i++) { 273 seqPanels[i].removeSequenceViewerListener(l); 274 } 275 } 276 277 public void addSequenceViewerMotionListener(SequenceViewerMotionListener l) { 278 motionListeners.add(l); 279 280 for (int i = 0; i < seqPanels.length; i++) { 281 seqPanels[i].addSequenceViewerMotionListener(l); 282 } 283 } 284 285 public void removeSequenceViewerMotionListener( 286 SequenceViewerMotionListener l) { 287 motionListeners.remove(l); 288 289 for (int i = 0; i < seqPanels.length; i++) { 290 seqPanels[i].removeSequenceViewerMotionListener(l); 291 } 292 } 293 294 public void setFont(Font f) { 295 try { 296 super.setFont(f); 297 298 for (int i = 0; i < seqPanels.length; i++) { 299 seqPanels[i].setFont(f); 300 seqPanels[i].resizeAndValidate(); 301 } 302 } catch (NullPointerException e) { 303 } 304 } 305 306 public void paint(Graphics g) { 307 // some wierd sequence graphics exception is going on in biojava 308 try { 309 super.paint(g); 310 } catch (Exception e) { 311 e.printStackTrace(); 312 System.out.println("Caught sequence graphics exception in paint() " 313 + e.toString()); 314 repaint(); 315 } 316 } 317 318 public void paintComponent(Graphics g) { 319 // some wierd sequence graphics exception is going on in biojava-1.3 320 try { 321 super.paintComponent(g); 322 } catch (Exception e) { 323 e.printStackTrace(); 324 System.out 325 .println("Caught sequence graphics exception in paintComponent() " 326 + e.toString()); 327 repaint(); 328 } 329 } 330} // class