com.actelion.research.gui.JChemistryView 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
/*
* @(#)JExtendedStructureView.java
*
* Copyright 2004 Actelion Ltd. All Rights Reserved.
*
* This software is the proprietary information of Actelion Ltd.
* Use is subject to license terms.
*
* @author Thomas Sander
*/
package com.actelion.research.gui;
import com.actelion.research.chem.*;
import com.actelion.research.chem.io.RXNFileParser;
import com.actelion.research.chem.reaction.Reaction;
import com.actelion.research.gui.clipboard.ClipboardHandler;
import com.actelion.research.gui.dnd.*;
import com.actelion.research.util.ColorHelper;
import com.actelion.research.util.CursorHelper;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.util.ArrayList;
public class JChemistryView extends JComponent
implements ActionListener,DragGestureListener,DragSourceListener,MouseListener,MouseMotionListener {
public static final int PASTE_AND_DROP_OPTION_ALLOW_FRAGMENT_STATE_CHANGE = 1;
public static final int PASTE_AND_DROP_OPTION_KEEP_ATOM_COLORS = 2;
public static final int PASTE_AND_DROP_OPTION_KEEP_BOND_HIGHLIGHTING = 4;
public static final int PASTE_AND_DROP_OPTION_REMOVE_CATALYSTS = 8;
public static final int PASTE_AND_DROP_OPTION_REMOVE_DRAWING_OBJECTS = 16;
public static final int PASTE_AND_DROP_OPTION_LAYOUT_REACTION = 32;
private static final String ITEM_COPY_RXN = "Copy Reaction";
private static final String ITEM_PASTE_RXN = "Paste Reaction";
private static final String ITEM_OPEN_RXN = "Open Reaction File";
private static final String ITEM_SAVE_RXN = "Save Reaction File";
private static final String ITEM_COPY_MOLS = "Copy Molecules";
private static final String ITEM_PASTE_MOLS = "Paste Molecules";
private static final long serialVersionUID = 20150204L;
private static final int UPDATE_REDRAW_ONLY = 0;
private static final int UPDATE_CHECK_COORDS = 1;
private static final int UPDATE_SCALE_COORDS = 2;
private static final int PASTE_AND_DROP_OPTIONS_DEFAULT = 0;
private static final int ALLOWED_DRAG_ACTIONS = DnDConstants.ACTION_COPY_OR_MOVE;
private static final int ALLOWED_DROP_ACTIONS = DnDConstants.ACTION_COPY_OR_MOVE;
private ExtendedDepictor mDepictor;
private ArrayList mListener;
private Dimension mSize;
private int mChemistryType,mUpdateMode,mDisplayMode,mDragMolecule,mCopyOrDragActions,mPasteOrDropActions,mPasteAndDropOptions;
private boolean mShowBorder,mIsDraggingThis,mAllowDropOrPasteWhenDisabled;
private Color mFragmentNoColor;
private MoleculeDropAdapter mMoleculeDropAdapter = null;
private ReactionDropAdapter mReactionDropAdapter = null;
/**
* Creates a new JChemistryView for showing a reaction or molecules.
* A JChemistryView uses an ExtendedDepictor to handle multiple molecules or a reaction.
* For showing one molecule use a JStructureView.
* This default implementation will support copy/paste and drag&drop.
* @param chemistryType one of ExtendedDepictor.TYPE_MOLECULES and ExtendedDepictor.TYPE_REACTION
*/
public JChemistryView(int chemistryType) {
this(chemistryType, ALLOWED_DRAG_ACTIONS, ALLOWED_DROP_ACTIONS);
}
/**
* Creates a new JChemistryView for showing a reaction or molecules.
* A JChemistryView uses an ExtendedDepictor to handle multiple molecules or a reaction.
* For showing one molecule use a JStructureView.
* @param chemistryType one of the ExtendedDepictor.TYPE_... options
* @param allowedCopyOrDragActions DnDConstants.ACTION_xxx
* @param allowedPasteOrDropActions DnDConstants.ACTION_xxx
*/
public JChemistryView(int chemistryType, int allowedCopyOrDragActions, int allowedPasteOrDropActions) {
mChemistryType = chemistryType;
mCopyOrDragActions = allowedCopyOrDragActions;
mPasteOrDropActions = allowedPasteOrDropActions;
mPasteAndDropOptions = PASTE_AND_DROP_OPTIONS_DEFAULT;
initializeDragAndDrop();
addMouseListener(this);
addMouseMotionListener(this);
mDragMolecule = -1;
}
public int getChemistryType() {
return mChemistryType;
}
public void setContent(StereoMolecule mol) {
setContent(mol, null);
}
public void setContent(StereoMolecule mol[]) {
setContent(mol, null);
}
public void setContent(Reaction rxn) {
setContent(rxn, null);
}
public void setContent(StereoMolecule mol, DrawingObjectList drawingObjectList) {
mDepictor = new ExtendedDepictor(mol, drawingObjectList, true);
mDepictor.setDisplayMode(mDisplayMode);
mDepictor.setFragmentNoColor(mFragmentNoColor);
mUpdateMode = UPDATE_SCALE_COORDS;
mDragMolecule = -1;
repaint();
}
public void setContent(StereoMolecule[] mol, DrawingObjectList drawingObjectList) {
mDepictor = new ExtendedDepictor(mol, drawingObjectList, true);
mDepictor.setDisplayMode(mDisplayMode);
mDepictor.setFragmentNoColor(mFragmentNoColor);
mUpdateMode = UPDATE_SCALE_COORDS;
mDragMolecule = -1;
repaint();
}
public void setContent(Reaction rxn, DrawingObjectList drawingObjectList) {
mDepictor = new ExtendedDepictor(rxn, drawingObjectList, rxn == null ? false : rxn.isReactionLayoutRequired(), true);
mDepictor.setDisplayMode(mDisplayMode);
mDepictor.setFragmentNoColor(mFragmentNoColor);
mUpdateMode = UPDATE_SCALE_COORDS;
mDragMolecule = -1;
repaint();
}
/**
* fragment status change on drop is allowed then dropping a fragment (molecule)
* on a molecule (fragment) inverts the status of the view's chemical object.
* As default status changes are prohibited.
* @param options flag list of PASTE_AND_DROP_OPTION...
*/
public void setPasteAndDropOptions(int options) {
mPasteAndDropOptions = options;
}
public void setAllowDropOrPasteWhenDisabled(boolean b) {
mAllowDropOrPasteWhenDisabled = b;
}
@Override
public void setEnabled(boolean enable) {
boolean changed = (enable != isEnabled());
super.setEnabled(enable);
if (changed) {
if (mMoleculeDropAdapter != null)
mMoleculeDropAdapter.setActive(enable);
if (mReactionDropAdapter != null)
mReactionDropAdapter.setActive(enable);
if (enable)
mDepictor.setOverruleColor(null, null);
else
mDepictor.setOverruleColor(ColorHelper.getContrastColor(Color.GRAY, getBackground()), getBackground());
repaint();
}
}
public void setFragmentNoColor(Color c) {
// use setFragmentNoColor(null) if you don't want fragment numbers to be shown
mFragmentNoColor = c;
if (mDepictor != null)
mDepictor.setFragmentNoColor(c);
}
public void setDisplayMode(int displayMode) {
mDisplayMode = displayMode;
if (mDepictor != null)
mDepictor.setDisplayMode(displayMode);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (mDepictor == null)
return;
Dimension theSize = getSize();
if (theSize.width == 0 || theSize.height == 0)
return;
Insets insets = getInsets();
theSize.width -= insets.left + insets.right;
theSize.height -= insets.top + insets.bottom;
if (mSize == null
|| mSize.width != theSize.width
|| mSize.height != theSize.height
|| mUpdateMode == UPDATE_SCALE_COORDS) {
mDepictor.validateView(g, new Rectangle2D.Double(insets.left, insets.top, theSize.width, theSize.height),
AbstractDepictor.cModeInflateToMaxAVBL);
}
else if (mUpdateMode == UPDATE_CHECK_COORDS) {
mDepictor.validateView(g, new Rectangle2D.Double(insets.left, insets.top, theSize.width, theSize.height), 0);
}
mSize = theSize;
// g.setColor(getBackground());
// g.fillRect(0, 0, theSize.width, theSize.height);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
mDepictor.setForegroundColor(getForeground(), getBackground());
mDepictor.paint(g);
if (mShowBorder) {
g.setColor(Color.gray);
g.drawRect(insets.left,insets.top,theSize.width - 1,theSize.height - 1);
g.drawRect(insets.left + 1,insets.top + 1,theSize.width - 3,theSize.height - 3);
}
mUpdateMode = UPDATE_REDRAW_ONLY;
}
private void updateBorder(boolean showBorder) {
if(mShowBorder != showBorder){
mShowBorder = showBorder;
repaint();
}
}
@Override public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(ITEM_COPY_MOLS)) {
ClipboardHandler ch = new ClipboardHandler();
if (mDepictor.getMoleculeCount() == 1) {
ch.copyMolecule(mDepictor.getMolecule(0));
}
else {
StereoMolecule mol = new StereoMolecule();
for (int i=0; i();
mListener.add(l);
}
public void removeStructureListener(StructureListener l) {
if(mListener != null)
mListener.remove(l);
}
public void informListeners() {
if (mListener != null)
for (StructureListener l:mListener)
l.structureChanged(null);
}
public boolean canDrop() {
return (isEnabled() || mAllowDropOrPasteWhenDisabled) && !mIsDraggingThis;
}
private void initializeDragAndDrop() {
if (mCopyOrDragActions != DnDConstants.ACTION_NONE)
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, mCopyOrDragActions, this);
if(mPasteOrDropActions != DnDConstants.ACTION_NONE) {
if (mChemistryType == ExtendedDepictor.TYPE_MOLECULES) {
mMoleculeDropAdapter = new MoleculeDropAdapter() {
public void onDropMolecule(StereoMolecule m,Point pt) {
if (m != null && canDrop()) {
pasteOrDropMolecule(m);
onDrop();
}
updateBorder(false);
}
public void dragEnter(DropTargetDragEvent e) {
boolean drop = canDrop() && isDropOK(e) ;
if (!drop)
e.rejectDrag();
updateBorder(drop);
}
public void dragExit(DropTargetEvent e) {
updateBorder(false);
}
};
new DropTarget(this, mPasteOrDropActions, mMoleculeDropAdapter, true);
// new DropTarget(this,mAllowedDropAction,mDropAdapter,true, getSystemFlavorMap());
}
if (mChemistryType == ExtendedDepictor.TYPE_REACTION) {
mReactionDropAdapter = new ReactionDropAdapter() {
public void onDropReaction(Reaction r, Point pt) {
if (r != null && canDrop()) {
pasteOrDropReaction(r);
onDrop();
}
updateBorder(false);
}
public void dragEnter(DropTargetDragEvent e) {
boolean drop = canDrop() && isDropOK(e) ;
if (!drop)
e.rejectDrag();
updateBorder(drop);
}
public void dragExit(DropTargetEvent e) {
updateBorder(false);
}
};
new DropTarget(this, mPasteOrDropActions, mReactionDropAdapter, true);
// new DropTarget(this,mAllowedDropAction,mDropAdapter,true, getSystemFlavorMap());
}
}
}
private void pasteOrDropMolecule(StereoMolecule m) {
boolean isFragment = mDepictor.isFragment();
StereoMolecule mol = new StereoMolecule(m);
if ((mPasteAndDropOptions & PASTE_AND_DROP_OPTION_KEEP_ATOM_COLORS) == 0)
mol.removeAtomColors();
if ((mPasteAndDropOptions & PASTE_AND_DROP_OPTION_KEEP_BOND_HIGHLIGHTING) == 0)
mol.removeBondHiliting();
if ((mPasteAndDropOptions & PASTE_AND_DROP_OPTION_ALLOW_FRAGMENT_STATE_CHANGE) == 0)
mol.setFragment(isFragment);
setContent(mol);
repaint();
informListeners();
}
private void pasteOrDropReaction(Reaction r) {
boolean isFragment = mDepictor.isFragment();
Reaction rxn = new Reaction(r);
if ((mPasteAndDropOptions & PASTE_AND_DROP_OPTION_KEEP_ATOM_COLORS) == 0)
for (int m=0; m
© 2015 - 2025 Weber Informatics LLC | Privacy Policy