com.actelion.research.gui.editor.FXEditorPane Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
package com.actelion.research.gui.editor;
import com.actelion.research.chem.IDCodeParser;
import com.actelion.research.chem.MolfileParser;
import com.actelion.research.chem.StereoMolecule;
import com.actelion.research.chem.reaction.Reaction;
import com.actelion.research.gui.generic.GenericPoint;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class FXEditorPane extends BorderPane {
private FXEditorToolbar mToolBar;
private FXEditorArea mArea;
/**
* Creates a chemical editor panel to edit the given molecule.
* Query features can be edited, if the passed mol's fragment bit is true.
* @param mol
*/
public FXEditorPane(StereoMolecule mol) {
this(mol, 0);
}
/**
* Creates a chemical editor panel to draw a molecule, reaction, or set of molecules,
* depending on the mode.
* Query features can be edited, if the passed mol's fragment bit is true.
* @param mol
* @param mode GenericDrawArea.MODE_...
*/
public FXEditorPane(StereoMolecule mol, int mode) {
initialize(mol, mode);
}
/**
* Creates a chemical editor panel to edit multiple molecules.
* Each of these molecule may consist of multiple disconnected fragments.
* Atoms connected by bonds or being in close vicinity are recognized to belong to the
* same molecule, while more distant fragments are perceived as separated molecules.
* Query features can be edited, if the passed mols' fragment bits are true.
* @param mol
*/
public FXEditorPane(StereoMolecule[] mol) {
initialize(null, GenericEditorArea.MODE_MULTIPLE_FRAGMENTS);
mArea.getGenericDrawArea().setFragments(mol);
}
/**
* Creates a chemical editor panel to edit the given chemical reaction.
* Query features can be edited, if the passed rxn's fragment bit is true.
* @param rxn
*/
public FXEditorPane(Reaction rxn) {
initialize(null, GenericEditorArea.MODE_REACTION);
mArea.getGenericDrawArea().setReaction(rxn);
}
private void initialize(StereoMolecule mol, int mode) {
mArea = new FXEditorArea(mol != null ? mol : new StereoMolecule(), mode);
mToolBar = new FXEditorToolbar(mArea);
widthProperty().addListener((observable, oldValue, newValue) -> mArea.setWidth((double) newValue-mToolBar.getWidth()));
heightProperty().addListener((observable, oldValue, newValue) -> mArea.setHeight((double) newValue));
setLeft(mToolBar);
setCenter(new Pane(mArea));
initializeDragAndDrop();
}
public GenericEditorArea getDrawArea() {
return mArea.getGenericDrawArea();
}
public FXEditorArea getFXDrawArea() {
return mArea;
}
public void cleanStructure(){
mArea.getGenericDrawArea().toolChanged(GenericEditorToolbar.cButtonCleanStructure);
}
private void initializeDragAndDrop() {
setOnDragEntered(event -> {
/* the drag-and-drop gesture entered the target */
System.out.println("onDragEntered");
/* show to the user that it is an actual gesture target */
if (event.getGestureSource() != this &&
event.getDragboard().hasString()) {
// target.setFill(Color.GREEN);
}
event.consume();
});
setOnDragOver(event -> {
/* data is dragged over the target */
// System.out.println("onDragOver");
/* accept it only if it is not dragged from the same node
* and if it has a string data */
Dragboard db = event.getDragboard();
if (event.getGestureSource() != this && /*db.hasString() */ getAcceptedFormats(db).size() > 0) {
/* allow for both copying and moving, whatever user chooses */
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
});
setOnDragExited(event -> event.consume() );
setOnDragDropped(event -> {
/* data dropped */
System.out.println("onDragDropped");
/* if there is a string data on dragboard, read it and use it */
Dragboard db = event.getDragboard();
// Set formats = db.getContentTypes();
boolean success = false;
// for (DataFormat f : formats) {
// System.out.printf("D&D Format %s\n", f);
// }
List formats = getAcceptedFormats(db);
StereoMolecule m = new StereoMolecule();
for (DataFormat format : formats) {
if (isJavaFormat(format, MOLFILE_FORMAT)) {
MolfileParser p = new MolfileParser();
p.parse(m, db.getContent(format).toString());
success = true;
break;
}
}
if (!success && db.hasString()) {
try {
IDCodeParser p = new IDCodeParser(true);
p.parse(m, db.getString());
success = true;
} catch (Exception e) {
System.err.println("Cannot parse data for molecules ");
}
}
if (success) {
mArea.getGenericDrawArea().addPastedOrDropped(m, new GenericPoint(event.getX(), event.getY()));
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
event.consume();
});
// setOnDragDetected(event -> {
// /* drag was detected, start drag-and-drop gesture*/
// System.out.println("onDragDetected");
//
// /* allow any transfer mode */
// Dragboard db = source.startDragAndDrop(TransferMode.ANY);
//
// /* put a string on dragboard */
// ClipboardContent content = new ClipboardContent();
// content.putString(source.getText());
// db.setContent(content);
//
// event.consume();
// });
}
private static String MOLFILE_FORMAT = "JAVA_DATAFLAVOR:chemical/x-mdl-molfilev3; class=java.lang.String";
private List getAcceptedFormats(Dragboard db) {
Set formats = db.getContentTypes();
List res = new ArrayList<>();
for (DataFormat f : formats) {
if (f.equals(DataFormat.PLAIN_TEXT))
res.add(f);
else if (isJavaFormat(f, MOLFILE_FORMAT)) {
res.add(f);
}
}
return res;
}
private boolean isJavaFormat(DataFormat f, String identifier) {
Set s = f.getIdentifiers();
for (String a : s) {
if (a.equals(identifier)) {
return true;
}
}
return false;
}
}