/* *****************************************************************************
* Copyright (c) 2009 Ola Spjuth.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ola Spjuth - initial API and implementation
******************************************************************************/
package net.bioclipse.metaprint2d.ui.actions;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import net.sf.metaprint2d.MetaPrintResult;
import net.bioclipse.cdk.domain.ICDKMolecule;
import net.bioclipse.cdk.jchempaint.editor.JChemPaintEditor;
import net.bioclipse.cdk.jchempaint.view.ChoiceGenerator;
import net.bioclipse.cdk.jchempaint.view.JChemPaintView;
import net.bioclipse.cdk.ui.sdfeditor.editor.MoleculesEditor;
import net.bioclipse.cdk.ui.sdfeditor.editor.MultiPageMoleculesEditorPart;
import net.bioclipse.core.business.BioclipseException;
import net.bioclipse.metaprint2d.Metaprinter;
import net.bioclipse.metaprint2d.ui.Activator;
import net.bioclipse.metaprint2d.ui.MetaPrintGenerator;
import net.bioclipse.metaprint2d.ui.Metaprint2DConstants;
import net.bioclipse.metaprint2d.ui.business.IMetaPrint2DManager;
import net.bioclipse.metaprint2d.ui.model.MetaPrint2DCalculation;
import net.bioclipse.metaprint2d.ui.views.MetaPrint2DReportView;
import org.apache.log4j.Logger;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.handlers.HandlerUtil;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.renderer.RendererModel;
import org.openscience.cdk.renderer.generators.IGenerator;
import org.openscience.cdk.renderer.generators.IGeneratorParameter;
public class MetaPrint2DHandler extends AbstractHandler {
private static final Object TOGGLE_COMMAND_ID = "net.bioclipse.metaprint2d.toggleCommand";
private static boolean shouldAutorun=false;
Logger logger = Logger.getLogger( MetaPrint2DHandler.class );
public boolean shouldAutorun(){return shouldAutorun;};
public Object execute(ExecutionEvent event) throws ExecutionException {
//Make sure we are called from a supported editor
IEditorPart editor = HandlerUtil.getActiveEditor(event);
if (event.getCommand().getId().equals( TOGGLE_COMMAND_ID )){
shouldAutorun = !shouldAutorun;
if (!shouldAutorun)
return null;
}
//Turn off all external generators
turnOffAllExternalGenerators(editor);
//Turn on M2D Generator
MetaPrintGenerator.setVisible(true);
if (editor instanceof net.bioclipse.cdk.ui.sdfeditor.editor.MultiPageMoleculesEditorPart) {
return executeInMolTableEditor(editor);
}
else if ( editor instanceof JChemPaintEditor ) {
JChemPaintEditor jcp=(JChemPaintEditor)editor;
handleChangedListeners(jcp);
return executeInJCP(jcp);
}
//Not supported, just finish (should not happen)
logger.error("M2D called from unsupported editor: " + editor);
return null;
}
public void handleChangedListeners( JChemPaintEditor jcp ) {
//First, try to look up in map
IPropertyChangeListener jcplistener = Activator.getEditorListenerMap().get( jcp);
//If not found in map, create a new
if (jcplistener==null){
jcplistener = new IPropertyChangeListener() {
public void propertyChange( PropertyChangeEvent event ) {
if(event.getProperty().equals( JChemPaintEditor.
STRUCUTRE_CHANGED_EVENT )) {
// editor model has changed
// do stuff...
logger.debug
("M2D reacting: JCP editor model has changed");
IEditorPart editor=PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editor==null)
return;
JChemPaintEditor activejcp = null;
//Check if JCP is active editor
if ( editor instanceof JChemPaintEditor ){
activejcp = (JChemPaintEditor) editor;
}
//Check if Moltable editor is active, if so, extract jcp if visible
else if ( editor instanceof MultiPageMoleculesEditorPart ) {
IContextService contextService = (IContextService) PlatformUI.getWorkbench().
getService(IContextService.class);
for (Object cs : contextService.getActiveContextIds()){
if (MultiPageMoleculesEditorPart.JCP_CONTEXT.equals( cs )){
Object obj = ((MultiPageMoleculesEditorPart)
editor)
.getAdapter(JChemPaintEditor.class);
if (obj!= null){
activejcp=(JChemPaintEditor)obj;
}
}
}
}
if ( activejcp!=null ) {
JChemPaintEditor jcp = (JChemPaintEditor) event.getSource();
//Return if this event is not triggered for the active editor
if (jcp != activejcp)
return;
logger.debug("listenr found AC: " + jcp.getCDKMolecule().getAtomContainer());
if (shouldAutorun){
try {
executeInJCP( jcp );
} catch ( ExecutionException e ) {
}
}
else if (jcp.getCDKMolecule().getAtomContainer().getProperty(
Metaprint2DConstants.METAPRINT_RESULT_PROPERTY )
!=null){
jcp.getCDKMolecule().getAtomContainer().setProperty(
Metaprint2DConstants.METAPRINT_RESULT_PROPERTY, "");
logger.debug("Cleared jcp m2d prop");
jcp.update();
}
}
}
}
};
jcp.addPropertyChangedListener(jcplistener);
Activator.getEditorListenerMap().put( jcp, jcplistener );
}
}
public Object executeInJCP(JChemPaintEditor jcp) throws ExecutionException {
//Get the managers via OSGI
IMetaPrint2DManager m2d = Activator.getDefault().getMetaPrint2DManager();
// ICDKManager cdk = net.bioclipse.cdk.business.Activator.getDefault().getJavaCDKManager();
//Time m2d execution
Stopwatch watch=new Stopwatch();
watch.start();
//Remove explicit hydrogens
// net.bioclipse.cdk.business.Activator.getDefault().getJavaCDKManager().removeExplicitHydrogens( cdkmol );
net.bioclipse.cdk.jchempaint.Activator.getDefault().getJavaManager().removeExplicitHydrogens();
// net.bioclipse.cdk.jchempaint.Activator.getDefault().getJavaManager().updateImplicitHydrogenCounts();
ICDKMolecule cdkmol=jcp.getCDKMolecule();
// logger.debug("Execute found AC: " + jcp.getCDKMolecule().getAtomContainer());
//Get previous result from m2d in a map editor -> m2dcalculation
//If this is first, create entry in map for this editor
List<MetaPrintResult> scores;
MetaPrint2DCalculation calc=null;
if (m2d.getCalculationMap().containsKey(jcp)){
calc=m2d.getCalculationMap().get(jcp);
}else{
calc=new MetaPrint2DCalculation();
m2d.getCalculationMap().put((IEditorPart) jcp, calc);
}
//===========
//Predict m2d
//===========
try {
scores = m2d.calculate(cdkmol,true);
setTooltips(jcp, scores);
calc.setStatus("OK");
} catch (BioclipseException e) {
e.printStackTrace();
calc.setStatus(e.getMessage());
} catch (InvocationTargetException e) {
e.printStackTrace();
calc.setStatus(e.getMessage());
}
watch.stop();
calc.setCalculationTime(watch.toString());
calc.setDatabase(Metaprinter.getSpecies().name());
calc.setOperator(Metaprinter.getOperator());
//Turn on contributed generators
jcp.getWidget().setUseExtensionGenerators( true );
//manually update jcpeditor
jcp.update();
//Update linked views
updateLinkedViews();
return null;
}
private void updateLinkedViews() {
//Manually refresh m2d report view
IViewPart reportView = PlatformUI.getWorkbench().
getActiveWorkbenchWindow().getActivePage().
findView(MetaPrint2DReportView.VIEW_ID);
if (reportView!=null)
((MetaPrint2DReportView)reportView).refresh();
//Manually refresh 2D view as well
IViewPart jcpview = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().findView( JChemPaintView.VIEW_ID );
if (jcpview!=null)
((JChemPaintView)jcpview).refresh();
}
/**
* M2d is executed from e.g. SDFEditor
* @param part a MultiPageMoleculesEditorPart
* @return null, always
* @throws ExecutionException if errors
*/
public Object executeInMolTableEditor(IEditorPart part) throws ExecutionException {
MultiPageMoleculesEditorPart moltableTditor=(MultiPageMoleculesEditorPart)part;
IContextService contextService = (IContextService) PlatformUI.getWorkbench().
getService(IContextService.class);
if (contextService==null) return null;
for (Object cs : contextService.getActiveContextIds()){
if (MultiPageMoleculesEditorPart.JCP_CONTEXT.equals( cs )){
//JCP is active
Object obj = moltableTditor.getAdapter(JChemPaintEditor.class);
if (obj!= null){
JChemPaintEditor jcp=(JChemPaintEditor)obj;
handleChangedListeners(jcp);
return executeInJCP( jcp );
}
}
}
//Moltable is active
MoleculesEditor molEditor=moltableTditor.getMoleculesPage();
molEditor.setUseExtensionGenerators( true );
//Add configurator that calculates property and customizes rendering
molEditor.setRenderer2DConfigurator( new MetaPrint2DAtomColorConfigurator() );
//Manually update the moltable
molEditor.refresh();
//Update linked views
updateLinkedViews();
return null;
}
private void setTooltips(JChemPaintEditor jcpeditor, List<MetaPrintResult> scores) {
RendererModel model=jcpeditor.getWidget().getRenderer2DModel();
IAtomContainer ac = jcpeditor.getCDKMolecule().getAtomContainer();
//Store tooltips Atom -> String
HashMap<IAtom, String> currentToolTip=new HashMap<IAtom, String>();
//Add tooltip for atoms with result
for (MetaPrintResult res : scores){
StringWriter sw=new StringWriter();
PrintWriter pw=new PrintWriter(sw);
pw.printf( "%d/%d %1.2f" , res.getReactionCentreCount(), res.getSubstrateCount(), res.getNormalisedRatio());
String tt=sw.getBuffer().toString();
currentToolTip.put( ac.getAtom( res.getAtomNumber() ), tt );
}
//Configure JCP
model.setToolTipTextMap( currentToolTip );
}
/**
* Stopwatch to time M2D execution
* @author ola
*
*/
public class Stopwatch {
private long start;
private long stop;
public void start() {
start = System.currentTimeMillis(); // start timing
}
public void stop() {
stop = System.currentTimeMillis(); // stop timing
}
public long elapsedTimeMillis() {
return stop - start;
}
//return number of miliseconds
public String toString() {
return "" + elapsedTimeMillis() + " ms"; // print execution time
}
}
private void turnOffAllExternalGenerators(IEditorPart editor) {
//Switch off all other DS-generators!
List<IGenerator<IAtomContainer>> generators = ChoiceGenerator.getGeneratorsFromExtension();
JChemPaintEditor jcp=getJCPfromEditor(editor);
if (jcp==null) return;
RendererModel model = jcp.getWidget().getRenderer2DModel();
for(IGenerator generator: generators) {
List<IGeneratorParameter<?>> params = generator.getParameters();
if(params.isEmpty()) continue;
for (IGeneratorParameter param : params){
if (param.getDefault() instanceof Boolean) {
IGeneratorParameter<Boolean> bp= (IGeneratorParameter<Boolean>)param;
model.set(bp.getClass(), false);
}
}
}
}
private JChemPaintEditor getJCPfromEditor(IEditorPart editor) {
if (editor instanceof JChemPaintEditor) {
return (JChemPaintEditor)editor;
}
else if (editor instanceof MultiPageMoleculesEditorPart) {
MultiPageMoleculesEditorPart moltable = (MultiPageMoleculesEditorPart) editor;
if (moltable.isJCPVisible()){
Object obj = moltable.getSelectedPage();
if (obj instanceof JChemPaintEditor) {
return (JChemPaintEditor) obj;
}
}
}
return null;
}
}