/* * Copyright (c) 2014. Matthew Campbell <matthew.campbell@mq.edu.au>, David R. Damerell <david@nixbioinf.org>. * * This file is part of GlycanBuilder Vaadin Release and its affliated projects EUROCarbDB, UniCarb-DB and UniCarbKB. * * This program is free software free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GlycanBuilder Vaadin Release is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License (LICENSE.txt) for more details. * * You should have received a copy of the GNU General Public License * along with GlycanBuilder Vaadin Release. If not, see <http ://www.gnu.org/licenses/>. */ package ac.uk.icl.dell.vaadin.glycanbuilder; import static ac.uk.icl.dell.vaadin.glycanbuilder.Geometry.angle; import static ac.uk.icl.dell.vaadin.glycanbuilder.Geometry.center; import static ac.uk.icl.dell.vaadin.glycanbuilder.Geometry.distance; import static ac.uk.icl.dell.vaadin.glycanbuilder.Geometry.getExclusionRadius; import static ac.uk.icl.dell.vaadin.glycanbuilder.Geometry.translate; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.Stroke; import org.eurocarbdb.application.glycanbuilder.AbstractLinkageRenderer; import org.eurocarbdb.application.glycanbuilder.Geometry; import org.eurocarbdb.application.glycanbuilder.GlycanRenderer; import org.eurocarbdb.application.glycanbuilder.Linkage; import org.eurocarbdb.application.glycanbuilder.LinkageStyle; import org.eurocarbdb.application.glycanbuilder.Paintable; import org.eurocarbdb.application.glycanbuilder.Residue; import org.eurocarbdb.application.glycanbuilder.TextUtils; import ac.uk.icl.dell.vaadin.canvas.basiccanvas.BasicCanvas; import ac.uk.icl.dell.vaadin.canvas.shapes.BaseShape; public class LinkageRendererCanvas extends AbstractLinkageRenderer{ public LinkageRendererCanvas() { super(); } public LinkageRendererCanvas(GlycanRenderer src) { super(src); } @Override public void paintEdge(Paintable paintable, Linkage link, boolean selected, Rectangle parent_bbox, Rectangle parent_border_bbox, Rectangle child_bbox, Rectangle child_border_bbox) { if (link == null) return; BasicCanvas theCanvas=(BasicCanvas) paintable.getObject(); if(selected){ theCanvas.setLineWidth(3.); }else{ theCanvas.setLineWidth(2.); } createShape(paintable,link, parent_bbox, child_bbox); // paint linkage info if(theGraphicOptions.SHOW_INFO){ paintInfo(paintable,link,parent_bbox,parent_border_bbox,child_bbox,child_border_bbox); } } @Override public void paintInfo(Paintable paintable, Linkage link, Rectangle parent_bbox, Rectangle parent_border_bbox, Rectangle child_bbox, Rectangle child_border_bbox) { if (link == null || !theGraphicOptions.SHOW_INFO) return; LinkageStyle style = theLinkageStyleDictionary.getStyle(link); Residue child = link.getChildResidue(); if (style.showParentLinkage(link)){ paintInfo(paintable,link.getParentPositionsString(), parent_bbox, parent_border_bbox, child_bbox, child_border_bbox, true, false, link.hasMultipleBonds()); } if (style.showAnomericCarbon(link)){ paintInfo(paintable,link.getChildPositionsString(), parent_bbox, parent_border_bbox, child_bbox, child_border_bbox, false, true, link.hasMultipleBonds()); } if (style.showAnomericState(link, child.getAnomericState())){ paintInfo(paintable,TextUtils.toGreek(child.getAnomericState()), parent_bbox, parent_border_bbox, child_bbox, child_border_bbox, false, false, link.hasMultipleBonds()); } } @Override protected void paintInfo(Paintable paintable, String text, Rectangle p, Rectangle pb, Rectangle c, Rectangle cb, boolean toparent, boolean above, boolean multiple) { BasicCanvas theCanvas=(BasicCanvas) paintable.getObject(); try{ double scale=0.4; double width=theCanvas.calculateTextWidth(text, scale); Point pos = computePosition(new Dimension((int)width,(int)(12.*scale)), p, pb, c, cb, toparent, above, multiple); theCanvas.setFont("9pt Calibri"); theCanvas.setFillStyle("black"); theCanvas.textAlign("left"); theCanvas.fillText(text, Double.valueOf(pos.x), Double.valueOf(pos.y+2)); // //theGraphicOptions.LINKAGE_INFO_SIZE => will be the font scale factor // theCanvas.saveContext(); // theCanvas.setLineWidth(1.3); // theCanvas.beginPath(); // //This is an arbitrary correction factor, something's not compatible in computePosition with the HTML5 placement // theCanvas.renderText(text, pos.x, pos.y-8.2, .0,scale); // setStrokeColour(paintable,Color.BLACK); // theCanvas.stroke(); // theCanvas.restoreContext(); }catch(Exception ex){ ex.printStackTrace(); } } @Override protected Point computePosition(Dimension tb, Rectangle p, Rectangle pb,Rectangle c, Rectangle cb, boolean toparent, boolean above,boolean multiple) { Point cp = Geometry.center(p); Point cc = Geometry.center(c); double r = 0.5 * 12; double cx=0.,cy=0.,R=0.,angle=0.; if( toparent ) { cx = cp.x; cy = cp.y; angle = Geometry.angle(cc,cp); R = getExclusionRadius(cp,angle,pb)+2; } else { cx = c.x+c.width/2; cy = c.y+c.height/2; angle = Geometry.angle(cp,cc); R = getExclusionRadius(cc,angle,cb)+2; } double space = (multiple) ?4. :2.; boolean add = above; if( toparent ) add = !add; double tx=0.,ty=0.; if( add ) { tx = cx+(R+r)*Math.cos(angle)+(r+space)*Math.cos(angle-Math.PI/2.); ty = cy+(R+r)*Math.sin(angle)+(r+space)*Math.sin(angle-Math.PI/2.); } else { tx = cx+(R+r)*Math.cos(angle)+(r+space)*Math.cos(angle+Math.PI/2.); ty = cy+(R+r)*Math.sin(angle)+(r+space)*Math.sin(angle+Math.PI/2.); } tx -= tb.getWidth()/2; ty += tb.getHeight()/2; return new Point((int)tx,(int)ty); // Point cp = center(p); // Point cc = center(c); // // double r = .3 * 12; // //**double r = 0.5 * theGraphicOptions.LINKAGE_INFO_SIZE; // double cx = 0., cy = 0., R = 0., angle = 0.; // if (toparent) { // cx = cp.x; // cy = cp.y; // angle = angle(cc, cp); // R = getExclusionRadius(cp, angle, pb) + 2; // } else { // cx = c.x + c.width / 2; // cy = c.y + c.height / 2; // angle = angle(cp, cc); // R = getExclusionRadius(cc, angle, cb) + 2; // } // double space = (multiple) ? 4. : 2.; // // boolean add = above; // if (toparent) // add = !add; // // double tx = 0., ty = 0.; // if (add) { // tx = cx + (R + r) * Math.cos(angle) + (r + space) // * Math.cos(angle - Math.PI / 2.); // ty = cy + (R + r) * Math.sin(angle) + (r + space) // * Math.sin(angle - Math.PI / 2.); // } else { // tx = cx + (R + r) * Math.cos(angle) + (r + space) // * Math.cos(angle + Math.PI / 2.); // ty = cy + (R + r) * Math.sin(angle) + (r + space) // * Math.sin(angle + Math.PI / 2.); // } // // tx -= tb.getWidth() / 2; // ty += tb.getHeight() / 2; //return new Point((int) tx, (int) ty); } @SuppressWarnings("unused") private Stroke createStroke(Linkage link, boolean selected) { LinkageStyle style = theLinkageStyleDictionary.getStyle(link); if (style.isDashed()) { float[] dashes = { 5.f, 5.f }; return new BasicStroke((selected) ? 2.f : 1.f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.f, dashes, 0.f); } return new BasicStroke((selected) ? 2.f : 1.f); } private void paintLine(Paintable paintable,Point p1, Point p2, boolean multiple, Linkage link) { if(multiple){ //GeneralPath gp = new GeneralPath(); double a = angle(p1, p2); paintLine(paintable, translate(p1, 2. * Math.cos(a + Math.PI / 2), 2. * Math.sin(a + Math.PI / 2)), translate(p2, 2. * Math.cos(a + Math.PI / 2), 2. * Math.sin(a + Math.PI / 2)), false,link); paintLine(paintable, translate(p1, 2. * Math.cos(a - Math.PI / 2), 2. * Math.sin(a - Math.PI / 2)), translate(p2, 2. * Math.cos(a - Math.PI / 2), 2. * Math.sin(a - Math.PI / 2)), false,link); }else{ paintLine(paintable,p1, p2,link); } } private void paintLine(Paintable paintable,Point p1, Point p2, Linkage link) { BasicCanvas theCanvas=(BasicCanvas) paintable.getObject(); theCanvas.beginPath(); LinkageStyle style = theLinkageStyleDictionary.getStyle(link); if(style.isDashed()){ BaseShape.paintDashedLine(theCanvas, p1.x,p1.y,p2.x,p2.y); }else{ theCanvas.moveTo(p1.x, p1.y); theCanvas.lineTo(p2.x, p2.y); } theCanvas.closePath(); setStrokeColour(paintable,Color.BLACK); theCanvas.stroke(); } private void createCurve(Paintable paintable,Point p1, Point p2) { double cx = (p1.x + p2.x) / 2.; double cy = (p1.y + p2.y) / 2.; double r = distance(p1, p2) / 2.; double angle = angle(p1, p2); // start point double x1 = cx + r * Math.cos(angle); double y1 = cy + r * Math.sin(angle); // end point double x2 = cx + r * Math.cos(angle + Math.PI); double y2 = cy + r * Math.sin(angle + Math.PI); // ctrl point 1 double cx1 = cx + 0.1 * r * Math.cos(angle); double cy1 = cy + 0.1 * r * Math.sin(angle); double tx1 = cx1 + r * Math.cos(angle + Math.PI / 2.); double ty1 = cy1 + r * Math.sin(angle + Math.PI / 2.); // ctrl point 2 double cx2 = cx + 0.1 * r * Math.cos(angle + Math.PI); double cy2 = cy + 0.1 * r * Math.sin(angle + Math.PI); double tx2 = cx2 + r * Math.cos(angle - Math.PI / 2.); double ty2 = cy2 + r * Math.sin(angle - Math.PI / 2.); //Bit of a guess at this point BasicCanvas theCanvas=(BasicCanvas) paintable.getObject(); theCanvas.beginPath(); theCanvas.moveTo(x1, y1); theCanvas.bezierCurveTo(tx1, ty1, tx2, ty2, x2, y2); setStrokeColour(paintable,Color.BLACK); theCanvas.stroke(); theCanvas.closePath(); //return new CubicCurve2D.Double(x1, y1, ); } private void paintCurve(Paintable paintable,Point p1, Point p2, boolean multiple, Linkage link) { if (multiple) { double a = angle(p1, p2); paintCurve(paintable, translate(p1, 2. * Math.cos(a + Math.PI / 2), 2. * Math.sin(a + Math.PI / 2)), translate(p2, 2. * Math.cos(a + Math.PI / 2), 2. * Math.sin(a + Math.PI / 2)), false,link); paintCurve(paintable, translate(p1, 2. * Math.cos(a - Math.PI / 2), 2. * Math.sin(a - Math.PI / 2)), translate(p2, 2. * Math.cos(a - Math.PI / 2), 2. * Math.sin(a - Math.PI / 2)), false,link); } createCurve(paintable,p1, p2); } private void createShape(Paintable paintable,Linkage link, Rectangle parent_bbox, Rectangle child_bbox) { LinkageStyle style = theLinkageStyleDictionary.getStyle(link); String edge_style = style.getShape(); Point parent_center = center(parent_bbox); Point child_center = center(child_bbox); if (edge_style.equals("none")){ //return null; } if (edge_style.equals("empty")){ //return null; } if (edge_style.equals("line")){ paintLine(paintable,parent_center, child_center, link.hasMultipleBonds(),link); }else if (edge_style.equals("curve")){ paintCurve(paintable,parent_center, child_center, link.hasMultipleBonds(),link); }else{ paintLine(paintable,parent_center, child_center,link); } } final protected void setStrokeColour(Paintable paintable,Color colour){ BasicCanvas theCanvas=(BasicCanvas) paintable.getObject(); theCanvas.setStrokeStyle(colour.getRed(),colour.getGreen(), colour.getBlue()); } }