3
* $Date: 2007-05-01 18:33:49 +0200 (Tue, 01 May 2007) $
6
* Copyright (C) 2005-2007 The JChemPaint project
8
* Contact: jchempaint-devel@lists.sourceforge.net
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU Lesser General Public License
12
* as published by the Free Software Foundation; either version 2.1
13
* of the License, or (at your option) any later version.
14
* All we ask is that proper credit is given for our work, which includes
15
* - but is not limited to - adding the above copyright notice to the beginning
16
* of your source code files, and to any copyright notice that you may distribute
17
* with programs based on this work.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU Lesser General Public License for more details.
24
* You should have received a copy of the GNU Lesser General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28
package org.openscience.cdk.applications.jchempaint.action;
30
import java.awt.Toolkit;
31
import java.awt.datatransfer.Clipboard;
32
import java.awt.datatransfer.ClipboardOwner;
33
import java.awt.datatransfer.DataFlavor;
34
import java.awt.datatransfer.Transferable;
35
import java.awt.datatransfer.UnsupportedFlavorException;
36
import java.awt.event.ActionEvent;
37
import java.io.StringReader;
38
import java.io.StringWriter;
39
import java.io.Writer;
40
import java.lang.reflect.Constructor;
41
import java.util.Iterator;
43
import javax.swing.undo.UndoableEdit;
45
import org.openscience.cdk.ChemFile;
46
import org.openscience.cdk.ChemModel;
47
import org.openscience.cdk.DefaultChemObjectBuilder;
48
import org.openscience.cdk.Molecule;
49
import org.openscience.cdk.MoleculeSet;
50
import org.openscience.cdk.applications.jchempaint.JChemPaintModel;
51
import org.openscience.cdk.applications.undoredo.AddAtomsAndBondsEdit;
52
import org.openscience.cdk.geometry.GeometryTools;
53
import org.openscience.cdk.interfaces.IAtomContainer;
54
import org.openscience.cdk.interfaces.IChemFile;
55
import org.openscience.cdk.io.IChemObjectReader;
56
import org.openscience.cdk.io.IChemObjectWriter;
57
import org.openscience.cdk.io.MDLV2000Reader;
58
import org.openscience.cdk.io.MDLWriter;
59
import org.openscience.cdk.io.ReaderFactory;
60
import org.openscience.cdk.io.SVGWriter;
61
import org.openscience.cdk.layout.StructureDiagramGenerator;
62
import org.openscience.cdk.layout.TemplateHandler;
63
import org.openscience.cdk.renderer.Renderer2DModel;
64
import org.openscience.cdk.smiles.SmilesGenerator;
65
import org.openscience.cdk.smiles.SmilesParser;
66
import org.openscience.cdk.tools.manipulator.ChemFileManipulator;
69
* Action to copy/paste structures.
71
* @cdk.module jchempaint
72
* @author Egon Willighagen <e.willighagen@science.ru.nl>
75
public class CopyPasteAction extends JCPAction{
77
private static final long serialVersionUID = -3343207264261279526L;
79
private DataFlavor molFlavor = new DataFlavor(
80
"chemical/x-mdl-molfile", "mdl mol file format");
81
private DataFlavor svgFlavor = new DataFlavor(
82
"image/svg+xml", "scalable vector graphics");
83
private DataFlavor cmlFlavor = new DataFlavor(
84
"image/cml", "chemical markup language");
86
public void actionPerformed(ActionEvent e) {
88
handleSystemClipboard();
89
logger.info(" type ", type);
90
logger.debug(" source ", e.getSource());
91
JChemPaintModel jcpModel = jcpPanel.getJChemPaintModel();
92
Renderer2DModel renderModel = jcpModel.getRendererModel();
93
if ("copy".equals(type)) {
94
IAtomContainer tocopy = renderModel.getSelectedPart();
98
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
99
IAtomContainer tocopyclone=(IAtomContainer)tocopy.clone();
100
for(int i=0;i<tocopy.getAtomCount();i++){
101
tocopyclone.getAtom(i).setPoint2d(renderModel.getRenderingCoordinate(tocopy.getAtom(i)));
103
JcpSelection jcpselection=new JcpSelection(tocopyclone);
104
sysClip.setContents(jcpselection,null);
105
} else if ("paste".equals(type)) {
106
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
107
Transferable transfer = sysClip.getContents( null );
108
IChemObjectReader reader = null;
109
// if a MIME type is given ...
110
if (transfer!=null && (transfer.isDataFlavorSupported (molFlavor))) {
111
String mol = (String) transfer.getTransferData (molFlavor);
112
logger.debug("Dataflavor molFlavor found");
113
reader = new MDLV2000Reader(new StringReader(mol));
114
} else if(transfer!=null && (transfer.isDataFlavorSupported (DataFlavor.stringFlavor))) {
115
// otherwise, try to use the ReaderFactory...
116
logger.debug("Dataflavor stringFlavor found");
117
String content = (String) transfer.getTransferData (DataFlavor.stringFlavor);
119
reader = new ReaderFactory().createReader(new StringReader(content));
120
} catch (Exception exception) {
121
logger.warn("Pastes string is not recognized.");
124
IAtomContainer topaste = null;
125
if (reader != null) {
126
if (reader.accepts(Molecule.class)) {
127
topaste = (IAtomContainer) reader.read(new Molecule());
128
} else if (reader.accepts(ChemFile.class)) {
129
topaste = new Molecule();
130
IChemFile file = (IChemFile)reader.read(new ChemFile());
131
Iterator containers = ChemFileManipulator.getAllAtomContainers(file).iterator();
132
while (containers.hasNext()) {
133
topaste.add((IAtomContainer)containers.next());
137
if(topaste==null && transfer!=null && (transfer.isDataFlavorSupported (DataFlavor.stringFlavor))) {
139
SmilesParser sp = new SmilesParser(DefaultChemObjectBuilder.getInstance());
140
topaste = sp.parseSmiles((String) transfer.getTransferData (DataFlavor.stringFlavor));
141
StructureDiagramGenerator sdg = new StructureDiagramGenerator((Molecule)topaste);
142
sdg.setTemplateHandler(
143
new TemplateHandler(topaste.getBuilder())
145
sdg.generateCoordinates();
146
jcpPanel.scaleAndCenterMolecule(topaste,jcpPanel.getSize());
147
for(int i=0;i<topaste.getAtomCount();i++){
148
renderModel.getRenderingCoordinates().put(topaste.getAtom(i), topaste.getAtom(i).getPoint2d());
150
}catch(Exception ex){
154
if (topaste != null) {
155
topaste = (IAtomContainer)topaste.clone();
157
org.openscience.cdk.interfaces.IChemModel chemModel = jcpModel.getChemModel();
158
//translate the new structure a bit
159
GeometryTools.translate2D(topaste, 25, 25,jcpModel.getRendererModel().getRenderingCoordinates()); //in pixels
160
//paste the new structure into the active model
161
org.openscience.cdk.interfaces.IMoleculeSet moleculeSet = chemModel.getMoleculeSet();
162
if (moleculeSet == null) {
163
moleculeSet = new MoleculeSet();
164
chemModel.setMoleculeSet(moleculeSet);
166
moleculeSet.addMolecule(new Molecule(topaste));
167
// to ensure, that the molecule is shown in the actual visibile part of jcp
168
jcpPanel.scaleAndCenterMolecule((ChemModel)jcpPanel.getChemModel());
169
//make the pasted structure selected
170
renderModel.setSelectedPart(topaste);
172
UndoableEdit edit = new AddAtomsAndBondsEdit(chemModel, topaste, "Pasted something",jcpModel.getControllerModel());
173
jcpPanel.getUndoSupport().postEdit(edit);
176
} catch(Exception ex){
177
ex.printStackTrace();
181
void handleSystemClipboard()
183
Clipboard clipboard = jcpPanel.getToolkit().getSystemClipboard();
184
Transferable clipboardContent = clipboard.getContents(this);
185
DataFlavor flavors[]=clipboardContent.getTransferDataFlavors();
186
String text = "System.clipoard content";
187
for(int i=0;i<flavors.length;++i)
189
text+="\n\n Name: "+ flavors[i].getHumanPresentableName();
190
text+="\n MIME Type: "+flavors[i].getMimeType();
192
Class cl = flavors[i].getRepresentationClass();
193
if(cl==null) text+="null";
194
else text+=cl.getName();
199
class JcpSelection implements Transferable, ClipboardOwner {
200
private DataFlavor [] supportedFlavors = {
201
molFlavor, DataFlavor.stringFlavor, svgFlavor, cmlFlavor
208
public JcpSelection (IAtomContainer tocopy1) throws Exception{
209
Molecule tocopy=new Molecule(tocopy1);
211
StringWriter sw = new StringWriter();
212
new MDLWriter(sw).writeMolecule(tocopy);
213
this.mol=sw.toString();
214
SmilesGenerator sg=new SmilesGenerator();
215
smiles = sg.createSMILES(tocopy);
217
sw=new StringWriter();
218
IChemObjectWriter cow = new SVGWriter(sw);
223
sw = new StringWriter();
224
Class cmlWriterClass = null;
226
cmlWriterClass = this.getClass().getClassLoader().loadClass("org.openscience.cdk.io.CMLWriter");
227
} catch (Exception exception) {
228
logger.error("Could not load CMLWriter: ", exception.getMessage());
229
logger.debug(exception);
231
if (cmlWriterClass != null) {
232
cow = (IChemObjectWriter)cmlWriterClass.newInstance();
233
Constructor constructor = cow.getClass().getConstructor(new Class[]{Writer.class});
234
cow = (IChemObjectWriter)constructor.newInstance(new Object[]{sw});
241
public synchronized DataFlavor [] getTransferDataFlavors () {
242
return (supportedFlavors);
245
public boolean isDataFlavorSupported (DataFlavor parFlavor) {
246
for(int i=0;i<supportedFlavors.length;i++){
247
if(supportedFlavors[i].equals(parFlavor))
253
public synchronized Object getTransferData (DataFlavor parFlavor) throws UnsupportedFlavorException {
254
if (parFlavor.equals (molFlavor)) {
256
} else if(parFlavor.equals(DataFlavor.stringFlavor)) {
258
} else if(parFlavor.equals(cmlFlavor)) {
260
} else if(parFlavor.equals(svgFlavor)) {
263
throw new UnsupportedFlavorException (parFlavor);
267
public void lostOwnership (Clipboard parClipboard, Transferable parTransferable) {
268
System.out.println ("Lost ownership");