From: <gil...@us...> - 2009-06-11 12:06:57
|
Revision: 14607 http://cdk.svn.sourceforge.net/cdk/?rev=14607&view=rev Author: gilleain Date: 2009-06-11 12:06:55 +0000 (Thu, 11 Jun 2009) Log Message: ----------- More general implementation of atom labelling, allowing more combinations of charge/isotope/atomnumber/implicit hydrogens. Modified Paths: -------------- cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/BasicAtomGenerator.java cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/visitor/AWTDrawVisitor.java jchempaint/trunk/src/main/org/openscience/jchempaint/RenderPanel.java Added Paths: ----------- cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/elements/TextGroupElement.java cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/ExtendedAtomGenerator.java Added: cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/elements/TextGroupElement.java =================================================================== --- cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/elements/TextGroupElement.java (rev 0) +++ cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/elements/TextGroupElement.java 2009-06-11 12:06:55 UTC (rev 14607) @@ -0,0 +1,52 @@ +package org.openscience.cdk.renderer.elements; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +public class TextGroupElement extends TextElement { + + public enum Position { NW, SW, SE, NE, S, N, W, E }; + + public class Child { + + public final String text; + + public final String subscript; + + public final Position position; + + public Child(String text, Position position) { + this.text = text; + this.position = position; + this.subscript = null; + } + + public Child(String text, String subscript, Position position) { + this.text = text; + this.position = position; + this.subscript = subscript; + } + + } + + public final List<Child> children; + + public TextGroupElement(double x, double y, String text, Color color) { + super(x, y, text, color); + this.children = new ArrayList<Child>(); + } + + public void addChild(String text, Position position) { + this.children.add(new Child(text, position)); + } + + public void addChild(String text, String subscript, Position position) { + this.children.add(new Child(text, subscript, position)); + } + + public void accept(IRenderingVisitor v) { + v.visit(this); + } + +} Modified: cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/BasicAtomGenerator.java =================================================================== --- cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/BasicAtomGenerator.java 2009-06-10 19:09:35 UTC (rev 14606) +++ cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/BasicAtomGenerator.java 2009-06-11 12:06:55 UTC (rev 14607) @@ -51,38 +51,46 @@ } return elementGroup; } + + public boolean canDraw(IAtom atom, IAtomContainer ac, RendererModel model) { + // don't draw atoms without coordinates + if (atom == null || atom.getPoint2d() == null) { + return false; + } + // don't draw hydrogens unless explicitly asked to + if (isHydrogen(atom) && !model.getShowExplicitHydrogens()) { + return false; + } + + // don't draw carbons unless + if (isCarbon(atom) && !showCarbon(atom, ac, model)) { + return false; + } + + return true; + } + protected Color getColorForAtom(IAtom atom, RendererModel model) { return model.getAtomColor(atom, Color.BLACK); } public IRenderingElement generate( IAtomContainer ac, IAtom atom, RendererModel model) { - if (atom == null || atom.getPoint2d() == null) - return null; - - if (isHydrogen(atom) && !model.getShowExplicitHydrogens()) { - // don't draw hydrogen - return null; - } - - if (isCarbon(atom) && !showCarbon(atom, ac, model)) { - // don't draw carbon - return null; - } - - if (model.getIsCompact()) { + if (!canDraw(atom, ac, model)) { + return null; + } else if (model.getIsCompact()) { return this.generateCompactElement(atom, model); - } - - int alignment = 0; - if (isCarbon(atom)) { - alignment = GeometryTools.getBestAlignmentForLabel(ac, atom); } else { - alignment = GeometryTools.getBestAlignmentForLabelXY(ac, atom); + int alignment = 0; + if (isCarbon(atom)) { + alignment = GeometryTools.getBestAlignmentForLabel(ac, atom); + } else { + alignment = GeometryTools.getBestAlignmentForLabelXY(ac, atom); + } + + return generateElements(atom, alignment, model); } - - return generateElements(atom, alignment, model); } public IRenderingElement generateCompactElement( Added: cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/ExtendedAtomGenerator.java =================================================================== --- cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/ExtendedAtomGenerator.java (rev 0) +++ cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/generators/ExtendedAtomGenerator.java 2009-06-11 12:06:55 UTC (rev 14607) @@ -0,0 +1,130 @@ +package org.openscience.cdk.renderer.generators; + +import java.awt.Color; +import java.util.Stack; + +import javax.vecmath.Point2d; + +import org.openscience.cdk.interfaces.IAtom; +import org.openscience.cdk.interfaces.IAtomContainer; +import org.openscience.cdk.interfaces.IPseudoAtom; +import org.openscience.cdk.renderer.RendererModel; +import org.openscience.cdk.renderer.elements.IRenderingElement; +import org.openscience.cdk.renderer.elements.TextGroupElement; +import org.openscience.cdk.renderer.elements.TextGroupElement.Position; + +/** + * A generator for atoms with mass, charge, etc. + * + * @author maclean + * @cdk.module render + * + */ +public class ExtendedAtomGenerator extends BasicAtomGenerator { + + public IRenderingElement generate( + IAtomContainer ac, IAtom atom, RendererModel model) { + + if (!canDraw(atom, ac, model)) { + return null; + } else if (model.getIsCompact()) { + return this.generateCompactElement(atom, model); + } else { + String text; + if (atom instanceof IPseudoAtom) { + text = ((IPseudoAtom) atom).getLabel(); + } else { + text = atom.getSymbol(); + } + Point2d p = atom.getPoint2d(); + Color c = getColorForAtom(atom, model); + TextGroupElement textGroup = new TextGroupElement(p.x, p.y, text, c); + decorate(textGroup, ac, atom, model); + return textGroup; + } + } + + public void decorate(TextGroupElement textGroup, + IAtomContainer ac, + IAtom atom, + RendererModel model) { + Stack<Position> unused = getUnusedPositions(ac, atom); + + if (model.getDrawNumbers()) { + Position position = getNextPosition(unused); + String number = String.valueOf(ac.getAtomNumber(atom) + 1); + textGroup.addChild(number, position); + } + + if (model.getShowImplicitHydrogens()) { + int nH = atom.getHydrogenCount(); + if (nH > 0) { + Position position = getNextPosition(unused); + if (nH == 1) { + textGroup.addChild("H", position); + } else { + textGroup.addChild("H", String.valueOf(nH), position); + } + } + } + } + + private Position getNextPosition(Stack<Position> unused) { + if (unused.size() > 0) { + return unused.pop(); + } else { + return Position.N; + } + } + + public Stack<Position> getUnusedPositions(IAtomContainer ac, IAtom atom) { + Stack<Position> unused = new Stack<Position>(); + for (Position p : Position.values()) { + unused.add(p); + } + + for (IAtom connectedAtom : ac.getConnectedAtomsList(atom)) { + Position used = getPosition(atom, connectedAtom); + if (unused.contains(used)) { + unused.remove(used); + } + } + return unused; + } + + public Position getPosition(IAtom atom, IAtom connectedAtom) { + Point2d pA = atom.getPoint2d(); + Point2d pB = connectedAtom.getPoint2d(); + double dx = pB.x - pA.x; + double dy = pB.y - pA.y; + + final double DELTA = 0.2; + + if (dx < -DELTA) { // generally west + if (dy < -DELTA) { + return Position.NW; + } else if (dy > -DELTA && dy < DELTA) { + return Position.W; + } else { + return Position.SW; + } + } else if (dx > -DELTA && dx < DELTA) { // north or south + if (dy < -DELTA) { + return Position.N; + } else if (dy > -DELTA && dy < DELTA) { // right on top of the atom! + return Position.N; // XXX + } else { + return Position.S; + } + } else { // generally east + if (dy < -DELTA) { + return Position.NE; + } else if (dy > -DELTA && dy < DELTA) { + return Position.E; + } else { + return Position.SE; + } + } + } + +} Modified: cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/visitor/AWTDrawVisitor.java =================================================================== --- cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/visitor/AWTDrawVisitor.java 2009-06-10 19:09:35 UTC (rev 14606) +++ cdk/branches/jchempaint-primary/src/main/org/openscience/cdk/renderer/visitor/AWTDrawVisitor.java 2009-06-11 12:06:55 UTC (rev 14607) @@ -23,12 +23,15 @@ import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Font; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.Stroke; +import java.awt.font.TextAttribute; import java.awt.geom.Rectangle2D; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; import javax.vecmath.Point2d; @@ -44,6 +47,7 @@ import org.openscience.cdk.renderer.elements.PathElement; import org.openscience.cdk.renderer.elements.RectangleElement; import org.openscience.cdk.renderer.elements.TextElement; +import org.openscience.cdk.renderer.elements.TextGroupElement; import org.openscience.cdk.renderer.elements.WedgeLineElement; import org.openscience.cdk.renderer.font.AWTFontManager; import org.openscience.cdk.renderer.font.IFontManager; @@ -69,12 +73,17 @@ private final Map<Integer, BasicStroke> strokeMap = new HashMap<Integer, BasicStroke>(); + private final Map<TextAttribute, Object> map = + new Hashtable<TextAttribute, Object>(); + private final Graphics2D g; public AWTDrawVisitor(Graphics2D g) { this.g = g; this.fontManager = null; this.rendererModel = null; + + map.put(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB); } public void visitElementGroup(ElementGroup elementGroup) { @@ -298,7 +307,84 @@ this.g.drawLine(p1[0], p1[1], p2[0], p2[1]); } } + + public void visit(TextGroupElement textGroup) { + this.g.setFont(this.fontManager.getFont()); + Point p = + super.getTextBasePoint( + textGroup.text, textGroup.x, textGroup.y, g); + Rectangle2D textBounds = + this.getTextBounds(textGroup.text, textGroup.x, textGroup.y, g); + this.g.setColor(this.rendererModel.getBackColor()); + this.g.fill(textBounds); + this.g.setColor(textGroup.color); + this.g.drawString(textGroup.text, p.x, p.y); + + int x = (int) textBounds.getCenterX(); + int y = (int) textBounds.getCenterY(); + int x1 = (int) textBounds.getMinX(); + int y1 = (int) textBounds.getMinY(); + int x2 = p.x + (int)textBounds.getWidth(); + int y2 = (int) textBounds.getMaxY(); + int oW = x2 - x1; + int oH = y2 - y1; + for (TextGroupElement.Child child : textGroup.children) { + int cx; + int cy; + + switch (child.position) { + case NE: + cx = x2; + cy = y1; + break; + case N: + cx = x1; + cy = y1; + break; + case NW: + cx = x1 - oW; + cy = y1; + break; + case W: + cx = x1 - oW; + cy = p.y; + break; + case SW: + cx = x1 - oW; + cy = y1 + oH; + break; + case S: + cx = x1; + cy = y2 + oH; + break; + case SE: + cx = x2; + cy = y2 + oH; + break; + case E: + cx = x2; + cy = p.y; + break; + default: + cx = x; + cy = y; + break; + } + + this.g.drawString(child.text, cx, cy); + if (child.subscript != null) { + Rectangle2D childBounds = getTextBounds(child.text, cx, cy, g); + int scx = (int)(cx + (childBounds.getWidth() * 0.75)); + int scy = (int)(cy + (childBounds.getHeight() / 3)); + Font f = this.g.getFont(); // TODO : move to font manager + Font subscriptFont = f.deriveFont(f.getStyle(), f.getSize() - 2); + this.g.setFont(subscriptFont); + this.g.drawString(child.subscript, scx, scy); + } + } + } + public void visit(IRenderingElement element) { Color savedColor = this.g.getColor(); if (element instanceof ElementGroup) @@ -311,6 +397,8 @@ visit((ArrowElement) element); else if (element instanceof OvalElement) visit((OvalElement) element); + else if (element instanceof TextGroupElement) + visit((TextGroupElement) element); else if (element instanceof AtomSymbolElement) visit((AtomSymbolElement) element); else if (element instanceof TextElement) Modified: jchempaint/trunk/src/main/org/openscience/jchempaint/RenderPanel.java =================================================================== --- jchempaint/trunk/src/main/org/openscience/jchempaint/RenderPanel.java 2009-06-10 19:09:35 UTC (rev 14606) +++ jchempaint/trunk/src/main/org/openscience/jchempaint/RenderPanel.java 2009-06-11 12:06:55 UTC (rev 14607) @@ -66,6 +66,7 @@ import org.openscience.cdk.renderer.font.AWTFontManager; import org.openscience.cdk.renderer.generators.AtomContainerBoundsGenerator; import org.openscience.cdk.renderer.generators.BasicAtomGenerator; +import org.openscience.cdk.renderer.generators.ExtendedAtomGenerator; import org.openscience.cdk.renderer.generators.ExternalHighlightGenerator; import org.openscience.cdk.renderer.generators.HighlightAtomGenerator; import org.openscience.cdk.renderer.generators.HighlightBondGenerator; @@ -168,7 +169,8 @@ if(debug) generators.add(new AtomContainerBoundsGenerator()); generators.add(new RingGenerator()); - generators.add(new BasicAtomGenerator()); +// generators.add(new BasicAtomGenerator()); + generators.add(new ExtendedAtomGenerator()); generators.add(new LonePairGenerator()); generators.add(new RadicalGenerator()); generators.add(new ExternalHighlightGenerator()); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |