package org.seqcode.projects.seqview.paintable; import java.io.File; import java.awt.*; import java.util.*; import org.seqcode.data.seqdata.SeqHit; import org.seqcode.genome.location.Region; import org.seqcode.gseutils.*; import org.seqcode.projects.seqview.model.SeqDataModel; import org.seqcode.projects.seqview.model.SeqScaleModel; import org.seqcode.viz.DynamicAttribute; /** * Paints Sequencing data across a genomic region. * */ public abstract class SeqPainter extends RegionPaintable { protected SeqDataModel model; protected SeqScaleModel scale; protected DynamicAttribute attrib; protected Vector<Region> totalLayoutHits = new Vector<Region>(); protected NonOverlappingLayout<Region> totalLayout = new NonOverlappingLayout<Region>(); protected static java.util.List configurationFields = null; private SeqProperties props; public SeqPainter(SeqDataModel model) { super(); this.model = model; props = new SeqProperties(); scale = new SeqScaleModel(model); model.addEventListener(this); attrib = DynamicAttribute.getGlobalAttributes(); } public SeqProperties getProperties () {return props;} public void setProperties(SeqProperties p) {props = p;} public void savePropsInDir(File dir) { super.savePropsInDir(dir); saveModelPropsInDir(dir,model); } public void loadPropsInDir(File dir) { super.loadPropsInDir(dir); loadModelPropsInDir(dir,model); } public void cleanup() { super.cleanup(); model.removeEventListener(this); } public void setScaleModel(SeqScaleModel s) { scale = s; } public SeqScaleModel getScaleModel() {return scale;} public java.util.List<String> configurationKeyOrder() {return configurationFields;} protected static int xcoord(int base, int x1, int baseStart, double scale) { return x1 + (int)Math.round((double)(base - baseStart) * scale); } protected int calcX(int bp, int rstart, int rend, int x1, int x2) { double frac = (double)(bp - rstart) / (rend - rstart); return x1 + (int)Math.round(frac * (double)(x2 - x1)); } protected int calcY(int over, int minover, int maxover, int y1, int y2) { double frac = (double)(over - minover) / (double)(maxover - minover); return y2 - (int)Math.round(frac * (double)(y2 - y1)); } protected void drawStep(Graphics2D g, int px, int py, int pover, int x, int y, int over) { if(over > pover) { drawStepUp(g, px, py, x, y); } if(over < pover) { drawStepDown(g, px, py, x, y); } if(over==pover) { g.drawLine(px, py, x, y); } } protected void drawStepUp(Graphics2D g, int px, int py, int x, int y) { g.drawLine(px, py, x, py); g.drawLine(x, py, x, y); } protected void drawStepDown(Graphics2D g, int px, int py, int x, int y) { g.drawLine(px, py, px, y); g.drawLine(px, y, x, y); } public synchronized void eventRegistered(EventObject e) { if ((e.getSource() == model) || (e.getSource() == scale) && model.isReady() && ((scale == null) || scale.isReady())) { setCanPaint(true); setWantsPaint(true); totalLayoutHits = null; setLayoutHits(); notifyListeners(); } } public void removeEventListener(Listener<EventObject> l) { super.removeEventListener(l); if (!hasListeners()) { model.removeEventListener(this); } } protected void setLayoutHits() { if (canPaint() && totalLayoutHits == null) { Iterator<SeqHit> itr = model.getResults(); totalLayoutHits = new Vector<Region>(); while(itr.hasNext()) { SeqHit hit = itr.next(); totalLayoutHits.add(hit); } totalLayout.setRegions(totalLayoutHits); } } public void paintItem(Graphics2D g, int x1, int y1, int x2, int y2) { if (!canPaint()) { return; } if(!model.isReady()) { return; } if (getProperties().Overlapping) { paintOverlapping(g, x1, y1, x2, y2); } else { paintNonOverlapping(g, x1, y1, x2, y2); } /* draw the track label */ int width = x2 - x1; int height = y2 - y1; if(model.isDataError()){ g.setFont(attrib.getLargeLabelFont(width,height)); g.setColor(Color.RED); g.drawString("ReadDB Data Error: " +getLabel(),x1 + g.getFont().getSize()*2,y1 + g.getFont().getSize()*2); }else if (getProperties().DrawTrackLabel) { g.setFont(attrib.getLargeLabelFont(width,height)); g.setColor(Color.BLACK); g.drawString(getLabel(),x1,y1 + g.getFont().getSize() * 2); } } protected abstract void paintOverlapping(Graphics2D g, int x1, int y1, int x2, int y2); protected abstract void paintNonOverlapping(Graphics2D g, int x1, int y1, int x2, int y2); }