package org.seqcode.projects.seqview.paintable;
import java.awt.*;
import java.util.*;
import org.seqcode.genome.location.Named;
import org.seqcode.genome.location.Region;
import org.seqcode.genome.location.Stranded;
import org.seqcode.gseutils.*;
import org.seqcode.projects.seqview.model.RegionExpanderModel;
import org.seqcode.viz.DynamicAttribute;
import org.seqcode.viz.colors.ColorSet;
/* actually works on all regions. Has special behaviors for those that implement Stranded or Named */
public class NamedStrandedPainter extends RegionPaintable {
//private static ColorSet colors = new ColorSet();
private static int sMaxTracks = 12;
private RegionExpanderModel model;
private boolean dirty;
private int trackIndex[];
private ArrayList<Region> regions;
private int tracksUsed;
private NamedStrandedProperties props;
public NamedStrandedPainter(RegionExpanderModel model) {
super();
this.model = model;
model.addEventListener(this);
dirty = true;
props = new NamedStrandedProperties();
initLabels();
}
public NamedStrandedProperties getProperties() {return props;}
public int getMaxVertSpace() {
if (model.isReady()) {
if (dirty) {
doLayout();
}
return 30 * (tracksUsed > 1 ? tracksUsed : 1);
} else {
return 60;
}
}
public int getMinVertSpace() {
if (model.isReady()) {
if (dirty) {
doLayout();
}
return 30 * (tracksUsed > 1 ? tracksUsed : 1);
} else {
return 60;
}
}
public void setRegion(Region r) {
dirty = true;
super.setRegion(r);
}
public void cleanup() {
super.cleanup();
model.removeEventListener(this);
}
public String getLabel(Region r) {
if (r instanceof Named) {
return ((Named)r).getName();
} else {
return r.toString();
}
}
public Color getColor(Region r) {
//return colors.getColor(r.toString());
return props.BoxColor;
}
private void doLayout() {
Iterator<Region> iter = model.getResults();
regions = new ArrayList<Region>();
while (iter.hasNext()) {
Region f = iter.next();
regions.add(f);
}
int lastEnd[] = new int[sMaxTracks];
for (int i = 0; i < sMaxTracks; i++) { lastEnd[i] = -1;}
trackIndex = new int[regions.size()];
tracksUsed = 0;
for (int j = 0; j < regions.size(); j++) {
int minpos = regions.get(j).getStart();
int maxpos = regions.get(j).getEnd();
int minindex = -1, biggestspace = -1000000;
for (int i = 0; i < sMaxTracks; i++) {
if (lastEnd[i] == -1) {
continue;
}
int space = minpos - lastEnd[i];
if (space > biggestspace) {
biggestspace = space;
minindex = i;
}
}
if (minindex == -1 || biggestspace < 20) {
for (int i = 0; i < sMaxTracks; i++) {
int space = minpos - lastEnd[i];
if (space > biggestspace) {
biggestspace = space;
minindex = i;
}
}
}
lastEnd[minindex] = maxpos;
trackIndex[j] = minindex;
if (minindex >= tracksUsed) {
tracksUsed = minindex + 1;
}
}
dirty = false;
}
public void paintItem(Graphics2D g,
int ulx, int uly,
int lrx, int lry) {
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (!model.isReady()) {
System.err.println (" but not ready");
return;
}
if (dirty) {
doLayout();
}
int lineSpace = Math.abs(lry - uly);
int bottom = lry;
int trackY[] = new int[tracksUsed];
int lastx[] = new int[tracksUsed];
Font oldFont = g.getFont();
g.setFont(DynamicAttribute.getGlobalAttributes().getRegionLabelFont(lrx-ulx,lry-uly));
int fontsize = g.getFont().getSize();
Stroke oldStroke = g.getStroke();
g.setStroke(new BasicStroke(1));
int tracksize = (lineSpace / (tracksUsed + 1));
for (int i = 0; i < tracksUsed; i++) {
trackY[i] = bottom - (i + 1) * tracksize;
lastx[i] = -1000;
}
boolean drawtracklabel = props.DrawTrackLabel;
boolean drawgenenames = props.DrawNames;
boolean fillcolor = props.FillRectangles;
boolean alwaysDrawNames = props.AlwaysDrawNames;
boolean drewAnything = false;
clearLabels();
for (int j = 0; j < regions.size(); j++) {
Region f = regions.get(j);
//Color c = colors.getColor(f.toString());
Color c = props.BoxColor;
if (c == null) {
continue;
} else {
g.setColor(c);
}
String label = getLabel(f);
int min = f.getStart();
int max = f.getEnd();
int x1 = getXPos(min,
getRegion().getStart(), getRegion().getEnd(),
ulx,lrx);
int x2 = getXPos(max,
getRegion().getStart(), getRegion().getEnd(),
ulx,lrx);
int y = trackY[trackIndex[j]];
if(!fillcolor)
g.drawRect(x1, y, x2 - x1, tracksize);
else {
if (x2 == x1) {
x2++;
}
g.drawRect(x1, y, x2 - x1, tracksize);
g.fillRect(x1, y, x2 - x1, tracksize);
}
if (f instanceof Stranded) {
g.setColor(Color.black);
char str = ((Stranded)f).getStrand();
if (str == '+') {
g.drawLine(x1,y,x2,y + tracksize /2);
g.drawLine(x1,y+tracksize,x2,y + tracksize /2);
} else if (str == '-') {
g.drawLine(x2,y,x1,y + tracksize /2);
g.drawLine(x2,y+tracksize,x1,y + tracksize /2);
}
}
addLabel(x1,y, x2 - x1, tracksize,label);
int center = (x1+x2)/2;
int texthalf = (label.length() * fontsize)/2;
if (((center - texthalf > lastx[trackIndex[j]]) && drawgenenames) ||
alwaysDrawNames){
g.setColor(Color.black);
g.drawString(label, center - texthalf,y + tracksize);
}
drewAnything = true;
lastx[trackIndex[j]] = x2;
}
g.setStroke(oldStroke);
if (drawtracklabel && drewAnything) {
g.setColor(Color.BLACK);
g.drawString(getLabel(),ulx,lry);
}
g.setFont(oldFont);
}
public synchronized void eventRegistered(EventObject e) {
if (e.getSource() == model &&
model.isReady()) {
setCanPaint(true);
setWantsPaint(true);
notifyListeners();
}
}
public void removeEventListener(Listener<EventObject> l) {
super.removeEventListener(l);
if (!hasListeners()) {
model.removeEventListener(this);
}
}
public String toString() {
return "NTP " + getLabel();
}
}