package fr.orsay.lri.varna.models.annotations; import java.awt.Color; import java.awt.Shape; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import javax.xml.transform.sax.TransformerHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import fr.orsay.lri.varna.VARNAPanel; import fr.orsay.lri.varna.controlers.ControleurClicMovement; import fr.orsay.lri.varna.models.VARNAConfigLoader; import fr.orsay.lri.varna.models.rna.ModeleBase; import fr.orsay.lri.varna.models.rna.RNA; import fr.orsay.lri.varna.models.rna.VARNAPoint; import fr.orsay.lri.varna.utils.XMLUtils; import fr.orsay.lri.varna.views.VueHighlightRegionEdit; import fr.orsay.lri.varna.views.VueUI; public class HighlightRegionAnnotation implements Serializable { public static final String HEADER_TEXT = "HighlightRegionAnnotation"; private static final long serialVersionUID = 7087014168028684775L; public static final Color DEFAULT_OUTLINE_COLOR = Color.decode("#6ed86e"); public static final Color DEFAULT_FILL_COLOR = Color.decode("#bcffdd"); public static final double DEFAULT_RADIUS = 16.0; private Color _outlineColor = DEFAULT_OUTLINE_COLOR; private Color _fillColor = DEFAULT_FILL_COLOR; private double _radius = DEFAULT_RADIUS; private ArrayList _bases; public static String XML_ELEMENT_NAME = "region"; public static String XML_VAR_OUTLINE_NAME = "outline"; public static String XML_VAR_FILL_NAME = "fill"; public static String XML_VAR_RADIUS_NAME = "radius"; public void toXML(TransformerHandler hd) throws SAXException { AttributesImpl atts = new AttributesImpl(); atts.addAttribute("","",XML_VAR_OUTLINE_NAME,"CDATA",""+XMLUtils.toHTMLNotation(_outlineColor)); atts.addAttribute("","",XML_VAR_FILL_NAME,"CDATA",""+XMLUtils.toHTMLNotation(_fillColor)); atts.addAttribute("","",XML_VAR_RADIUS_NAME,"CDATA",""+_radius); hd.startElement("","",XML_ELEMENT_NAME,atts); XMLUtils.toXML(hd, _bases); hd.endElement("","",XML_ELEMENT_NAME); } public HighlightRegionAnnotation(RNA r, int startIndex, int stopIndex) { this(r.getBasesBetween(startIndex, stopIndex)); } public HighlightRegionAnnotation() { this(new ArrayList()); } public HighlightRegionAnnotation(ArrayList b) { this(b,DEFAULT_FILL_COLOR,DEFAULT_OUTLINE_COLOR,DEFAULT_RADIUS); } public HighlightRegionAnnotation(ArrayList b,Color fill, Color outline, double radius) { _bases = b; _fillColor = fill; _outlineColor = outline; _radius = radius; } public HighlightRegionAnnotation clone() { return new HighlightRegionAnnotation(_bases,_fillColor,_outlineColor,_radius); } public int getMinIndex() { int min = Integer.MAX_VALUE; for (ModeleBase mb : _bases) { min = Math.min(min, mb.getIndex()); } return min; } public int getMaxIndex() { int max = Integer.MIN_VALUE; for (ModeleBase mb : _bases) { max = Math.max(max, mb.getIndex()); } return max; } public void setOutlineColor(Color c) { _outlineColor = c; } public ArrayList getBases() { return _bases; } public void setBases(ArrayList b) { _bases = b; } public void setFillColor(Color c) { _fillColor = c; } public Color getFillColor() { return _fillColor; } public Color getOutlineColor() { return _outlineColor; } public double getRadius() { return _radius; } public void setRadius(double v) { _radius = v; } public static final int NUM_STEPS_ROUNDED_CORNERS = 16; private Point2D.Double symImage(Point2D.Double p, Point2D.Double center) { return new Point2D.Double(2.*center.x-p.x, 2.*center.y-p.y); } private LinkedList buildRoundedCorner(Point2D.Double p1, Point2D.Double p2, Point2D.Double anotherPoint) { LinkedList result = new LinkedList(); Point2D.Double m = new Point2D.Double((p1.x+p2.x)/2.0,(p1.y+p2.y)/2.0); double rad = p1.distance(p2)/2.; double angle = Math.atan2(p1.y-m.y, p1.x-m.x); double incr = Math.PI/((double)NUM_STEPS_ROUNDED_CORNERS+1); Point2D.Double pdir = new Point2D.Double(m.x+rad*Math.cos(angle+Math.PI/2.),m.y+rad*Math.sin(angle+Math.PI/2.)); if (pdir.distance(anotherPoint) pointList = new LinkedList(); for (int i = 0;i0) { Point2D.Double prev1 = pointList.getLast(); Point2D.Double prev2 = pointList.getFirst(); if ((interForward.distance(prev1)+interBackward.distance(prev2))<(interForward.distance(prev2)+interBackward.distance(prev1))) { pointList.addLast(interForward); pointList.addFirst(interBackward); } else { pointList.addFirst(interForward); pointList.addLast(interBackward); } } else { pointList.addLast(interForward); pointList.addFirst(interBackward); } } } if (getBases().size()==1) { int midl = pointList.size()/2; Point2D.Double mid = pointList.get(midl); Point2D.Double apoint = new Point2D.Double(mid.x+1.,mid.y); LinkedList pointListStart = buildRoundedCorner(pointList.get(midl-1), pointList.get(midl), apoint); pointList.addAll(midl, pointListStart); mid = pointList.get(midl); apoint = new Point2D.Double(mid.x+1.,mid.y); LinkedList pointListEnd = buildRoundedCorner(pointList.get(pointList.size()-1),pointList.get(0), apoint); pointList.addAll(0,pointListEnd); } else if (getBases().size()>1) { int midl = pointList.size()/2; Point2D.Double apoint = symImage(pointList.get(midl),pointList.get(midl-1)); LinkedList pointListStart = buildRoundedCorner(pointList.get(midl-1), pointList.get(midl), apoint); pointList.addAll(midl, pointListStart); apoint = symImage(realCoords[getBases().get(getBases().size()-1).getIndex()], realCoords[getBases().get(getBases().size()-2).getIndex()]); LinkedList pointListEnd = buildRoundedCorner(pointList.get(pointList.size()-1),pointList.get(0), apoint); pointList.addAll(0,pointListEnd); } if (pointList.size()>0) { Point2D.Double point = pointList.get(0); p.moveTo((float)point.x, (float)point.y); for (int i=1;i bases = vp.getRNA().getBasesBetween(i, j); if (parts.length>1) { try { String[] options = parts[1].split(","); for (int k = 0; k < options.length; k++) { //System.out.println(options[k]); try { String[] data = options[k].split("="); String lhs = data[0].toLowerCase(); String rhs = data[1]; if (lhs.equals("fill")) { fill = VARNAConfigLoader.getSafeColor(rhs, fill); } else if (lhs.equals("outline")) { outline = VARNAConfigLoader.getSafeColor(rhs, outline); } else if (lhs.equals("radius")) { radius = Double.parseDouble(rhs); } } catch(Exception e) { } } } catch(Exception e) { e.printStackTrace(); } } return new HighlightRegionAnnotation(bases,fill,outline,radius); } catch(Exception e) { e.printStackTrace(); } return null; } public String toString() { //String result = "HighlightRegionAnnotation["; //result += "fill:"+_fillColor.toString(); //result += ",outline:"+_outlineColor.toString(); //result += ",radius:"+_radius; //return result+"]"; String result = "Highlighted region "+getMinIndex()+"-"+getMaxIndex(); return result; } }