/**
* Copyright (c) 2005-2013 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.
*/
/*
* Author: atotic
* Created on May 6, 2004
*/
package org.python.pydev.debug.model;
import java.io.File;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.core.model.IWatchExpression;
import org.eclipse.debug.internal.ui.DefaultLabelProvider;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IValueDetailListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorInput;
import org.python.pydev.core.log.Log;
import org.python.pydev.debug.core.PydevDebugPlugin;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.editorinput.EditorInputFactory;
import org.python.pydev.shared_core.string.StringUtils;
import org.python.pydev.shared_ui.ImageCache;
/**
* Provides decoration for model elements in the debugger interface.
*/
@SuppressWarnings("restriction")
public class PyDebugModelPresentation implements IDebugModelPresentation {
static public String PY_DEBUG_MODEL_ID = "org.python.pydev.debug";
/**
* Listeners compared by identity
*/
protected ListenerList fListeners = new ListenerList(ListenerList.IDENTITY);
protected boolean displayVariableTypeNames = false; // variables display attribute
private boolean returnNullForDefaultHandling;
private DefaultLabelProvider defaultDebugLabelProvider;
public PyDebugModelPresentation() {
this(true);
}
public PyDebugModelPresentation(boolean returnNullForDefaultHandling) {
this.returnNullForDefaultHandling = returnNullForDefaultHandling;
if (!returnNullForDefaultHandling) {
try {
defaultDebugLabelProvider = new DefaultLabelProvider();
} catch (Throwable e) {
//As it's discouraged access, let's prevent from having an error if it disappears in the future.
Log.log(e);
}
}
}
/**
* @return the image for some debug element
*/
@Override
public Image getImage(Object element) {
ImageCache imageCache = PydevDebugPlugin.getImageCache();
if (element instanceof PyBreakpoint) {
try {
PyBreakpoint pyBreakpoint = (PyBreakpoint) element;
if (pyBreakpoint.isEnabled()) {
if (pyBreakpoint.getType().equals(PyBreakpoint.PY_BREAK_TYPE_DJANGO)) {
return imageCache.get("icons/breakmarker_django.png");
} else {
if (pyBreakpoint.isConditionEnabled()) {
return imageCache.get("icons/breakmarker_conditional.gif");
} else {
return imageCache.get("icons/breakmarker.gif");
}
}
} else {
if (pyBreakpoint.getType().equals(PyBreakpoint.PY_BREAK_TYPE_DJANGO)) {
return imageCache.get("icons/breakmarker_django_gray.png");
} else {
if (pyBreakpoint.isConditionEnabled()) {
return imageCache.get("icons/breakmarker_gray_conditional.gif");
} else {
return imageCache.get("icons/breakmarker_gray.gif");
}
}
}
} catch (CoreException e) {
PydevDebugPlugin.log(IStatus.ERROR, "getImage error", e);
}
} else if (element instanceof PyVariableCollection) {
PyVariableCollection pyVariableCollection = (PyVariableCollection) element;
if (pyVariableCollection.isReturnValue()) {
return imageCache.get("icons/return_value.png");
}
return imageCache.get("icons/greendot_big.gif");
} else if (element instanceof PyVariable) {
PyVariable pyVariable = (PyVariable) element;
if (pyVariable.isReturnValue()) {
return imageCache.get("icons/return_value.png");
}
return imageCache.get("icons/greendot.gif");
} else if (element instanceof CaughtException) {
return imageCache.get("icons/python_exception_breakpoint.png");
} else if (element instanceof PyDebugTarget || element instanceof PyThread || element instanceof PyStackFrame) {
if (element instanceof PyThread) {
if (((PyThread) element).isCustomFrame) {
return imageCache.get("icons/tasklet.png");
}
}
if (returnNullForDefaultHandling) {
return null;
}
if (defaultDebugLabelProvider != null) {
return defaultDebugLabelProvider.getImage(element);
}
}
return null;
}
/**
* @return the text for some debug element
*/
@Override
public String getText(Object element) {
if (element instanceof PyBreakpoint) {
PyBreakpoint pyBreakpoint = (PyBreakpoint) element;
IMarker marker = ((PyBreakpoint) element).getMarker();
try {
Map<String, Object> attrs = marker.getAttributes();
//get the filename
String ioFile = pyBreakpoint.getFile();
String fileName = "unknown";
if (ioFile != null) {
File file = new File(ioFile);
fileName = file.getName();
}
//get the line number
Object lineNumber = attrs.get(IMarker.LINE_NUMBER);
String functionName = pyBreakpoint.getFunctionName();
if (lineNumber == null) {
lineNumber = "unknown";
}
//get the location
String location = fileName + ":" + lineNumber.toString();
if (functionName == null) {
return location;
} else {
return functionName + " [" + location + "]";
}
} catch (CoreException e) {
PydevDebugPlugin.log(IStatus.ERROR, "error retreiving marker attributes", e);
return "error";
}
} else if (element instanceof AbstractDebugTarget || element instanceof PyStackFrame
|| element instanceof PyThread) {
if (returnNullForDefaultHandling) {
return null;
}
if (element instanceof AbstractDebugTarget) {
AbstractDebugTarget abstractDebugTarget = (AbstractDebugTarget) element;
try {
return abstractDebugTarget.getName();
} catch (DebugException e) {
Log.log(e);
}
}
if (element instanceof PyStackFrame) {
PyStackFrame pyStackFrame = (PyStackFrame) element;
try {
return pyStackFrame.getName();
} catch (DebugException e) {
Log.log(e);
}
}
if (element instanceof PyThread) {
PyThread pyThread = (PyThread) element;
try {
return pyThread.getName();
} catch (DebugException e) {
Log.log(e);
}
}
return null; // defaults work
} else if (element instanceof CaughtException) {
CaughtException caughtException = (CaughtException) element;
String text = this.getText(caughtException.threadNstack.thread);
return StringUtils.join("",
new String[] { caughtException.excType, ": ", caughtException.msg, " - ", text });
} else if (element instanceof IVariable) {
if (returnNullForDefaultHandling) {
return null;
}
IVariable iVariable = (IVariable) element;
return getVariableText(iVariable); // defaults are fine
} else if (element instanceof IWatchExpression) {
try {
IWatchExpression watch_expression = (IWatchExpression) element;
IValue value = watch_expression.getValue();
if (value != null) {
return "\"" + watch_expression.getExpressionText() + "\"= " + value.getValueString();
} else {
return null;
}
} catch (DebugException e) {
return null;
}
} else if (element == null) {
PydevDebugPlugin.log(IStatus.ERROR, "PyDebugModelPresentation: element == null", null);
return null;
} else {
PydevDebugPlugin.log(IStatus.ERROR, "PyDebugModelPresentation:\nclass not expected for presentation:"
+ element.getClass() + "\n(returning default presentation).", null);
return null;
}
}
protected String getVariableText(IVariable variable) {
try {
return StringUtils.join(" = ", variable.getName(), variable.getValue().getValueString());
} catch (DebugException e) {
Log.log(e);
}
try {
return variable.getName();
} catch (DebugException e) {
Log.log(e);
}
return null;
}
/**
* We've got some work to do to replicate here, because we can't return null, and have LazyModel presentation do the
* default
*/
@Override
public void computeDetail(IValue value, IValueDetailListener listener) {
if (value instanceof PyVariable) {
try {
((PyVariable) value).getVariables();
listener.detailComputed(value, ((PyVariable) value).getDetailText());
} catch (DebugException e) {
PydevDebugPlugin.errorDialog("Unexpected error fetching variable", e);
}
}
}
/**
* Returns editor to be displayed
*/
@Override
public IEditorInput getEditorInput(Object element) {
if (element instanceof PyBreakpoint) {
String file = ((PyBreakpoint) element).getFile();
if (file != null) {
return EditorInputFactory.create(new File(file), false);
//We should not open the editor here, just create the input... the debug framework opens it later on.
//IPath path = new Path(file);
//IEditorPart part = PyOpenEditor.doOpenEditor(path);
//return part.getEditorInput();
}
}
return null;
}
/**
* @see org.eclipse.debug.ui.ISourcePresentation#getEditorInput
*/
@Override
public String getEditorId(IEditorInput input, Object element) {
return PyEdit.EDITOR_ID;
}
@Override
public void setAttribute(String attribute, Object value) {
if (attribute.equals(IDebugModelPresentation.DISPLAY_VARIABLE_TYPE_NAMES)) {
displayVariableTypeNames = ((Boolean) value).booleanValue();
} else {
Log.log("setattribute");
}
}
@Override
public void addListener(ILabelProviderListener listener) {
fListeners.add(listener);
}
@Override
public void removeListener(ILabelProviderListener listener) {
fListeners.remove(listener);
}
@Override
public void dispose() {
}
@Override
public boolean isLabelProperty(Object element, String property) {
// Not really sure what this does. see IBaseLabelProvider:isLabelProperty
return false;
}
}