1 /* 2 * Copyright (c) 2015 John May <jwmay@users.sf.net> 3 * 4 * Contact: cdk-devel@lists.sourceforge.net 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation; either version 2.1 of the License, or (at 9 * your option) any later version. All we ask is that proper credit is given 10 * for our work, which includes - but is not limited to - adding the above 11 * copyright notice to the beginning of your source code files, and to any 12 * copyright notice that you may distribute with programs based on this work. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17 * License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 U 22 */ 23 24 package org.openscience.cdk.renderer.elements; 25 26 import org.openscience.cdk.interfaces.IAtom; 27 import org.openscience.cdk.interfaces.IAtomContainer; 28 import org.openscience.cdk.interfaces.IBond; 29 import org.openscience.cdk.interfaces.IChemObject; 30 31 import java.util.ArrayList; 32 import java.util.Collections; 33 import java.util.List; 34 35 /** 36 * A marked element adds meta-data (id and tags) to a CDK rendering 37 * element (or group of elements). The id should be unique per depiction. 38 * The primary use case it to be able to set the 'id' and 'class' 39 * attributes in SVG. 40 * 41 * To set the mol, atom, or bond id set a String property to {@link #ID_KEY}. 42 * Similarly, the {@link #CLASS_KEY} can be used to set the classes. 43 * 44 * <pre>{@code 45 * IAtomContainer mol; 46 * atom.setProperty(MarkedElement.ID_KEY, "my_atm_id"); 47 * atom.setProperty(MarkedElement.CLASS_KEY, "h_donor"); 48 * atom.setProperty(MarkedElement.CLASS_KEY, "h_acceptor"); 49 * }</pre> 50 */ 51 public final class MarkedElement implements IRenderingElement { 52 53 public static final String ID_KEY = MarkedElement.class.getName() + "_ID"; 54 public static final String CLASS_KEY = MarkedElement.class.getName() + "_CLS"; 55 56 final IRenderingElement elem; 57 private String id; 58 private final List<String> classes = new ArrayList<>(5); 59 MarkedElement(IRenderingElement elem)60 private MarkedElement(IRenderingElement elem) { 61 this.elem = elem; 62 } 63 64 /** 65 * Set the identifier of the tagged element. 66 * 67 * @param id the id 68 */ setId(String id)69 private void setId(String id) { 70 this.id = id; 71 } 72 73 /** 74 * Add a cls to the element. 75 * 76 * @param cls a cls 77 */ aggClass(String cls)78 private void aggClass(String cls) { 79 if (cls != null) 80 this.classes.add(cls); 81 } 82 83 /** 84 * Access the id of the element. 85 * 86 * @return id, null if none 87 */ getId()88 public String getId() { 89 return id; 90 } 91 92 /** 93 * Access the classes of the element. 94 * 95 * @return id, empty if none 96 */ getClasses()97 public List<String> getClasses() { 98 return Collections.unmodifiableList(classes); 99 } 100 101 /** 102 *{@inheritDoc} 103 */ 104 @Override accept(IRenderingVisitor visitor)105 public void accept(IRenderingVisitor visitor) { 106 visitor.visit(this); 107 } 108 109 /** 110 * Access the element of which the id and classes apply. 111 * 112 * @return rendering element 113 */ element()114 public IRenderingElement element() { 115 return elem; 116 } 117 118 /** 119 * Markup a rendering element with the specified classes. 120 * 121 * @param elem rendering element 122 * @param classes classes 123 * @return the marked element 124 */ markup(IRenderingElement elem, String... classes)125 public static MarkedElement markup(IRenderingElement elem, String... classes) { 126 assert elem != null; 127 MarkedElement tagElem = new MarkedElement(elem); 128 for (String cls : classes) 129 tagElem.aggClass(cls); 130 return tagElem; 131 } 132 markupChemObj(IRenderingElement elem, IChemObject chemObj)133 private static MarkedElement markupChemObj(IRenderingElement elem, IChemObject chemObj) { 134 assert elem != null; 135 MarkedElement tagElem = new MarkedElement(elem); 136 if (chemObj != null) { 137 tagElem.setId(chemObj.getProperty(ID_KEY, String.class)); 138 tagElem.aggClass(chemObj.getProperty(CLASS_KEY, String.class)); 139 } 140 return tagElem; 141 } 142 143 /** 144 * Markup a molecule with the class 'mol' and optionally the ids/classes 145 * from it's properties. 146 * 147 * @param elem rendering element 148 * @param mol molecule 149 * @return the marked element 150 */ markupMol(IRenderingElement elem, IAtomContainer mol)151 public static MarkedElement markupMol(IRenderingElement elem, IAtomContainer mol) { 152 assert elem != null; 153 MarkedElement tagElem = markupChemObj(elem, mol); 154 tagElem.aggClass("mol"); 155 return tagElem; 156 } 157 158 /** 159 * Markup a atom with the class 'atom' and optionally the ids/classes 160 * from it's properties. 161 * 162 * @param elem rendering element 163 * @param atom atom 164 * @return the marked element 165 */ markupAtom(IRenderingElement elem, IAtom atom)166 public static MarkedElement markupAtom(IRenderingElement elem, IAtom atom) { 167 if (elem == null) 168 return null; 169 MarkedElement tagElem = markupChemObj(elem, atom); 170 tagElem.aggClass("atom"); 171 return tagElem; 172 } 173 174 /** 175 * Markup a bond with the class 'bond' and optionally the ids/classes 176 * from it's properties. 177 * 178 * @param elem rendering element 179 * @param bond bond 180 * @return the marked element 181 */ markupBond(IRenderingElement elem, IBond bond)182 public static MarkedElement markupBond(IRenderingElement elem, IBond bond) { 183 assert elem != null; 184 MarkedElement tagElem = markupChemObj(elem, bond); 185 tagElem.aggClass("bond"); 186 return tagElem; 187 } 188 } 189