/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.debug.model;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.ui.DeferredDebugElementWorkbenchAdapter;
import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
import org.eclipse.ui.progress.IElementCollector;
import org.python.pydev.core.log.Log;
import org.python.pydev.debug.model.remote.AbstractDebuggerCommand;
import org.python.pydev.debug.model.remote.GetVariableCommand;
import org.python.pydev.debug.model.remote.ICommandResponseListener;
public class DeferredWorkbenchAdapter extends DeferredDebugElementWorkbenchAdapter implements
IDeferredWorkbenchAdapter, ICommandResponseListener {
private volatile PyVariable[] commandVariables;
private AbstractDebugTarget target;
private IVariableLocator locator;
private final Object parent;
private IProgressMonitor monitor;
public DeferredWorkbenchAdapter(Object parent) {
this.parent = parent;
}
@Override
public boolean isContainer() {
if (parent instanceof PyVariableCollection) {
return true;
} else if (parent instanceof PyStackFrame) {
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.ui.progress.IDeferredWorkbenchAdapter#fetchDeferredChildren(java.lang.Object, org.eclipse.ui.progress.IElementCollector, org.eclipse.core.runtime.IProgressMonitor)
*/
public void fetchDeferredChildren(Object object, IElementCollector collector, IProgressMonitor monitor) {
this.monitor = monitor;
if (monitor.isCanceled()) {
return;
}
Object[] children = getChildren(object);
if (monitor.isCanceled()) {
return;
}
if (children != null && children.length > 0) {
collector.add(children, monitor);
}
collector.done();
}
public Object[] getChildren(Object o) {
if (parent != o) {
throw new RuntimeException("This is valid only for a single getChildren!");
}
if (o instanceof PyVariableCollection) {
PyVariableCollection variableCollection = (PyVariableCollection) o;
target = variableCollection.getTarget();
if (target != null) {
locator = variableCollection;
GetVariableCommand variableCommand = variableCollection.getVariableCommand(target);
variableCommand.setCompletionListener(this);
target.postCommand(variableCommand);
return waitForCommand();
}
return new Object[0];
} else if (o instanceof PyStackFrame) {
PyStackFrame f = (PyStackFrame) o;
target = f.getTarget();
if (target != null) {
locator = f;
GetVariableCommand variableCommand = f.getFrameCommand(target);
variableCommand.setCompletionListener(this);
target.postCommand(variableCommand);
return waitForCommand();
}
return new Object[0];
} else if (o instanceof PyVariable) {
return new Object[0];
} else {
throw new RuntimeException("Unexpected class: " + o.getClass());
}
}
private PyVariable[] waitForCommand() {
try {
// VariablesView does not deal well with children changing asynchronously.
// it causes unneeded scrolling, because view preserves selection instead
// of visibility.
// I try to minimize the occurrence here, by giving pydevd time to complete the
// task before we are forced to do asynchronous notification.
int i = 500; //up to 5 seconds
while (--i > 0 && commandVariables == null) {
if (this.monitor != null && this.monitor.isCanceled() == true) {
//canceled request... let's return
return new PyVariable[0];
}
Thread.sleep(10); //10 millis
}
} catch (InterruptedException e) {
Log.log(e);
}
if (commandVariables != null) {
return commandVariables;
}
return new PyVariable[0];
}
public Object getParent(Object o) {
//do we really need that?
return parent;
}
public void commandComplete(AbstractDebuggerCommand cmd) {
PyVariable[] temp = PyVariableCollection.getCommandVariables(cmd, target, locator);
if (parent instanceof PyVariableCollection) {
commandVariables = temp;
} else if (parent instanceof PyStackFrame) {
PyStackFrame f = (PyStackFrame) parent;
PyVariable[] temp1 = new PyVariable[temp.length + 1];
System.arraycopy(temp, 0, temp1, 1, temp.length);
temp1[0] = new PyVariableCollection(target, "Globals", "frame.f_globals", "Global variables",
f.getGlobalLocator());
commandVariables = temp1;
} else {
throw new RuntimeException("Unknown parent:" + parent.getClass());
}
}
}