- added support for detail formatters 'toString' preferences
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/DLTKDebugUIPlugin.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/DLTKDebugUIPlugin.java
index 3a3ed4e..71a54bd 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/DLTKDebugUIPlugin.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/DLTKDebugUIPlugin.java
@@ -13,8 +13,6 @@
 import java.util.Map;
 
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdapterFactory;
-import org.eclipse.core.runtime.IAdapterManager;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IExtension;
 import org.eclipse.core.runtime.IExtensionPoint;
@@ -24,7 +22,6 @@
 import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.debug.core.ILaunchManager;
 import org.eclipse.debug.internal.ui.DebugUIPlugin;
-import org.eclipse.debug.internal.ui.LazyModelPresentation;
 import org.eclipse.debug.ui.IDebugModelPresentation;
 import org.eclipse.debug.ui.IDebugUIConstants;
 import org.eclipse.debug.ui.ILaunchConfigurationTab;
@@ -100,10 +97,9 @@
 		launchManager.addLaunchListener(DebugConsoleManager.getInstance());
 		launchManager.addLaunchListener(ScriptDebugLogManager.getInstance());
 
-		IAdapterManager manager = Platform.getAdapterManager();
-
-		IAdapterFactory variableFactory = new ScriptDebugElementAdapterFactory();
-		manager.registerAdapters(variableFactory, IScriptVariable.class);
+		Platform.getAdapterManager().registerAdapters(
+				ScriptDebugElementAdapterFactory.getInstance(),
+				IScriptVariable.class);
 
 		ScriptDebugOptionsManager.getDefault().startup();
 
@@ -156,6 +152,7 @@
 			setShuttingDown(true);
 
 			ScriptDebugOptionsManager.getDefault().shutdown();
+			ScriptDebugElementAdapterFactory.getInstance().dispose();
 
 			ILaunchManager launchManager = DebugPlugin.getDefault()
 					.getLaunchManager();
@@ -297,8 +294,8 @@
 		if (shell != null) {
 			ErrorDialog
 					.openError(shell,
-							"DebugUIM0essages.JDIDebugUIPlugin_Error_1", //$NON-NLS-1$
-							message, status);
+					"DebugUIM0essages.JDIDebugUIPlugin_Error_1", //$NON-NLS-1$
+					message, status);
 		}
 	}
 
@@ -314,8 +311,8 @@
 					"Error logged from DLTK Debug UI: ", t); //$NON-NLS-1$	
 			ErrorDialog
 					.openError(shell,
-							"DebugUIMessages.JDIDebugUIPlugin_Error_1", //$NON-NLS-1$
-							message, status);
+					"DebugUIMessages.JDIDebugUIPlugin_Error_1", //$NON-NLS-1$
+					message, status);
 		}
 	}
 
@@ -402,7 +399,7 @@
 
 	public synchronized ScriptDebugModelPresentation getModelPresentation(
 			String modelId) {
-		if (!fPresentations.containsKey(modelId)) {			
+		if (!fPresentations.containsKey(modelId)) {
 			fPresentations.put(modelId, loadDebugModelPresentation(modelId));
 		}
 		return (ScriptDebugModelPresentation) fPresentations.get(modelId);
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/IDLTKDebugUILanguageToolkit.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/IDLTKDebugUILanguageToolkit.java
index 1c9d649..f6ba2bd 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/IDLTKDebugUILanguageToolkit.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/IDLTKDebugUILanguageToolkit.java
@@ -5,6 +5,11 @@
 public interface IDLTKDebugUILanguageToolkit {
 
 	/**
+	 * Returns the plugin debug model id.
+	 */
+	String getDebugModelId();
+
+	/**
 	 * Returns the <code>IPreferenceStore</code> implementation that is used to
 	 * store language specific debug ui preferences.
 	 */
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugElementAdapterFactory.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugElementAdapterFactory.java
index dbff173..af30029 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugElementAdapterFactory.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugElementAdapterFactory.java
@@ -1,50 +1,108 @@
 package org.eclipse.dltk.debug.ui;
 
-import org.eclipse.core.runtime.IAdapterFactory;
-import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter;
-import org.eclipse.dltk.debug.core.model.IScriptVariable;
+import java.util.HashMap;
+import java.util.Iterator;
 
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter;
+import org.eclipse.dltk.debug.core.model.IScriptDebugTarget;
+import org.eclipse.dltk.debug.core.model.IScriptVariable;
+import org.eclipse.dltk.internal.debug.ui.variables.ScriptVariableLabelProvider;
+import org.eclipse.dltk.ui.DLTKUILanguageManager;
+import org.eclipse.jface.preference.IPreferenceStore;
 
 public class ScriptDebugElementAdapterFactory implements IAdapterFactory {
-	
-	//private static final IElementLabelProvider fgLPVariable = new JavaVariableLabelProvider();
-	//private static final IElementContentProvider fgCPVariable = new JavaVariableContentProvider();
-	//private static final IElementLabelProvider fgLPExpression = new ExpressionLabelProvider();
-	//private static final IElementContentProvider fgCPExpression = new JavaExpressionContentProvider();
+
+	private static ScriptDebugElementAdapterFactory instance;
+	// assume only 1 plugin installed
+	private HashMap variableLabelProviders = new HashMap(1);
+
+	// private static final IElementLabelProvider fgLPVariable = new
+	// ScriptVariableLableProvider();
+	// private static final IElementContentProvider fgCPVariable = new
+	// JavaVariableContentProvider();
+	// private static final IElementLabelProvider fgLPExpression = new
+	// ExpressionLabelProvider();
+	// private static final IElementContentProvider fgCPExpression = new
+	// JavaExpressionContentProvider();
+
 	private static final IWatchExpressionFactoryAdapter watchExpressionFactory = new ScriptWatchExpressionFilter();
 
+	public static ScriptDebugElementAdapterFactory getInstance() {
+		if (instance == null) {
+			instance = new ScriptDebugElementAdapterFactory();
+		}
+
+		return instance;
+	}
+
+	private ScriptDebugElementAdapterFactory() {
+		// private constructor
+	}
+
 	public Object getAdapter(Object adaptableObject, Class adapterType) {
-		/*if (IElementLabelProvider.class.equals(adapterType)) {
-			if (adaptableObject instanceof IJavaVariable) {
-				return fgLPVariable; 
+		if (IElementLabelProvider.class.equals(adapterType)) {
+			if (adaptableObject instanceof IScriptVariable) {
+				return getVariableLabelProvider((IDebugElement) adaptableObject);
 			}
-			if (adaptableObject instanceof JavaInspectExpression) {
-				return fgLPExpression;
-			}
-		}*/
-		
-		/*if (IElementContentProvider.class.equals(adapterType)) {
-			if (adaptableObject instanceof IJavaVariable) {
-				return fgCPVariable;
-			}
-			if (adaptableObject instanceof JavaInspectExpression) {
-				return fgCPExpression;
-			}
-		}*/
-		
+		}
+		/*
+		 * if (adaptableObject instanceof JavaInspectExpression) { return
+		 * fgLPExpression; } }
+		 */
+
+		/*
+		 * if (IElementContentProvider.class.equals(adapterType)) { if
+		 * (adaptableObject instanceof IJavaVariable) { return fgCPVariable; }
+		 * if (adaptableObject instanceof JavaInspectExpression) { return
+		 * fgCPExpression; } }
+		 */
+
 		if (IWatchExpressionFactoryAdapter.class.equals(adapterType)) {
 			if (adaptableObject instanceof IScriptVariable) {
 				return watchExpressionFactory;
 			}
-			/*if (adaptableObject instanceof JavaInspectExpression) {
-				return fgCPExpression;
-			}*/
+			/*
+			 * if (adaptableObject instanceof JavaInspectExpression) { return
+			 * fgCPExpression; }
+			 */
 		}
 		return null;
 	}
 
 	public Class[] getAdapterList() {
-		return new Class[]{/*IElementLabelProvider.class,IElementContentProvider.class,*/IWatchExpressionFactoryAdapter.class};
+		return new Class[] { IElementLabelProvider.class,
+		// IElementContentProvider.class,
+				IWatchExpressionFactoryAdapter.class };
 	}
 
+	public void dispose() {
+		disposeVariableLabelProviders();
+	}
+
+	private void disposeVariableLabelProviders() {
+		Iterator iter = variableLabelProviders.entrySet().iterator();
+		while (iter.hasNext()) {
+			((ScriptVariableLabelProvider) iter.next()).dispose();
+		}
+	}
+
+	private IPreferenceStore getPreferenceStore(IDebugElement element) {
+		String natureId = ((IScriptDebugTarget) element.getDebugTarget())
+				.getLanguageToolkit().getNatureId();
+		return DLTKUILanguageManager.getLanguageToolkit(natureId)
+				.getPreferenceStore();
+	}
+
+	private Object getVariableLabelProvider(IDebugElement toAdapt) {
+		String id = toAdapt.getModelIdentifier();
+		if (!variableLabelProviders.containsKey(id)) {
+			variableLabelProviders.put(id, new ScriptVariableLabelProvider(
+					getPreferenceStore(toAdapt)));
+		}
+
+		return variableLabelProviders.get(id);
+	}
 }
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugModelPresentation.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugModelPresentation.java
index de047db..22e3e37 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugModelPresentation.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/ScriptDebugModelPresentation.java
@@ -53,6 +53,7 @@
 import org.eclipse.dltk.debug.ui.breakpoints.BreakpointUtils;
 import org.eclipse.dltk.internal.core.Openable;
 import org.eclipse.dltk.internal.core.util.HandleFactory;
+import org.eclipse.dltk.internal.debug.ui.DetailFormatter;
 import org.eclipse.dltk.internal.debug.ui.ExternalFileEditorInput;
 import org.eclipse.dltk.internal.debug.ui.ScriptDetailFormattersManager;
 import org.eclipse.dltk.internal.debug.ui.ScriptEvaluationContextManager;
@@ -63,6 +64,7 @@
 import org.eclipse.dltk.launching.debug.DebuggingEngineManager;
 import org.eclipse.dltk.launching.debug.IDebuggingEngine;
 import org.eclipse.dltk.ui.DLTKUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.IRegion;
@@ -248,9 +250,18 @@
 		return stackFrame.toString();
 	}
 
+	protected String getVariableName(IScriptVariable variable)
+			throws DebugException {
+		return variable.getName();
+	}
+
+	/**
+	 * Returns the text that will be displayed in the Variable view when the
+	 * 'Show Columns' layout option <strong>is not</strong> enabled.
+	 */
 	public String getVariableText(IScriptVariable variable) {
 		try {
-			String name = variable.getName();
+			String name = getVariableName(variable);
 			IScriptValue value = (IScriptValue) variable.getValue();
 			if (value != null) {
 				if (isShowVariableTypeNames()) {
@@ -260,7 +271,9 @@
 						name = typeName + " " + name; //$NON-NLS-1$
 					}
 				}
+
 				String valueText = getValueText(value);
+
 				if (valueText != null && valueText.length() > 0) {
 					return name + " = " + valueText; //$NON-NLS-1$
 				}
@@ -274,17 +287,84 @@
 		return variable.toString();
 	}
 
-	protected String getValueText(IScriptValue value) {
-		try {
-			return value.getValueString();
-		} catch (DebugException e) {
-			DebugPlugin.log(e);
+	/**
+	 * Returns <code>true</code> if the contents of the variable should be
+	 * displayed in the Variables view instead of information about the variable
+	 * type.
+	 */
+	protected boolean isShowLabelDetails(IScriptValue value) {
+		IScriptDebugTarget target = (IScriptDebugTarget) value.getDebugTarget();
+		String natureId = target.getLanguageToolkit().getNatureId();
+
+		IPreferenceStore store = DLTKDebugUILanguageManager.getLanguageToolkit(
+				natureId).getPreferenceStore();
+		String details = store
+				.getString(IDLTKDebugUIPreferenceConstants.PREF_SHOW_DETAILS);
+
+		boolean showDetails = false;
+		if (IDLTKDebugUIPreferenceConstants.INLINE_ALL.equals(details)) {
+			showDetails = true;
+		} else if (IDLTKDebugUIPreferenceConstants.INLINE_FORMATTERS
+				.equals(details)) {
+			DetailFormatter formatter = ScriptDetailFormattersManager
+					.getDefault(natureId).getDetailFormatter(value);
+			showDetails = (formatter != null && formatter.isEnabled());
 		}
-		return value.toString();
+
+		return showDetails;
 	}
 
+	/**
+	 * Returns the text that will be displayed in the Variable view when the
+	 * 'Show Columns' layout option <strong>is</strong> enabled.
+	 */
+	protected String getValueText(IScriptValue value) {
+		String text = null;
+		if (isShowLabelDetails(value)) {
+			// the same value shown in the details pane will be displayed here
+			text = getVariableDetail(value);
+		} else {
+			try {
+				text = value.getValueString();
+			} catch (DebugException e) {
+				DebugPlugin.log(e);
+				text = value.toString();
+			}
+		}
+
+		return text;
+	}
+
+	private String getVariableDetail(IScriptValue value) {
+		final String[] detail = new String[1];
+		final Object lock = new Object();
+		computeDetail(value, new IValueDetailListener() {
+			public void detailComputed(IValue computedValue, String result) {
+				synchronized (lock) {
+					detail[0] = result;
+					lock.notifyAll();
+				}
+			}
+		});
+		synchronized (lock) {
+			if (detail[0] == null) {
+				try {
+					lock.wait(5000);
+				} catch (InterruptedException e1) {
+					// Fall through
+				}
+			}
+		}
+		return detail[0];
+	}
+
+	/**
+	 * Returns the text that will be displayed in the 'details' pane of the
+	 * Variables view. This method will be invoked when no detail formatter is
+	 * available for the script variable.
+	 */
 	public String getDetailPaneText(IScriptValue value) {
-		return getValueText(value);
+		return value.getDetailsString();
 	}
 
 	protected String renderUnknownValue(IScriptValue value)
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/ScriptDetailFormattersManager.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/ScriptDetailFormattersManager.java
index 1ed3baa..6498dbc 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/ScriptDetailFormattersManager.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/ScriptDetailFormattersManager.java
@@ -2,10 +2,14 @@
 
 import java.util.HashMap;
 
+import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
 import org.eclipse.debug.ui.IValueDetailListener;
 import org.eclipse.dltk.core.DLTKCore;
 import org.eclipse.dltk.core.SimpleDLTKExtensionManager;
@@ -13,12 +17,17 @@
 import org.eclipse.dltk.debug.core.eval.IScriptEvaluationCommand;
 import org.eclipse.dltk.debug.core.eval.IScriptEvaluationListener;
 import org.eclipse.dltk.debug.core.eval.IScriptEvaluationResult;
+import org.eclipse.dltk.debug.core.model.IScriptStackFrame;
 import org.eclipse.dltk.debug.core.model.IScriptThread;
 import org.eclipse.dltk.debug.core.model.IScriptValue;
+import org.eclipse.dltk.debug.ui.DLTKDebugUILanguageManager;
 import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin;
+import org.eclipse.dltk.debug.ui.IDLTKDebugUIPreferenceConstants;
 import org.eclipse.dltk.debug.ui.ScriptDebugModelPresentation;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
 
-public class ScriptDetailFormattersManager {
+public class ScriptDetailFormattersManager implements IPropertyChangeListener {
 	private static final String DEFAULT_FORMATTER_TYPE = "#DEFAULT#"; //$NON-NLS-1$
 	private static final String ATTR_SNIPPET = "snippet"; //$NON-NLS-1$
 	private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
@@ -48,8 +57,11 @@
 		return instance;
 	}
 
-	public ScriptDetailFormattersManager(String natureId) {
+	private ScriptDetailFormattersManager(String natureId) {
 		populateDetailFormatters(natureId);
+
+		DLTKDebugUILanguageManager.getLanguageToolkit(natureId)
+				.getPreferenceStore().addPropertyChangeListener(this);
 	}
 
 	private void populateDetailFormatters(String natureId) {
@@ -75,8 +87,9 @@
 
 	private String getValueText(IValue value) {
 		if (value instanceof IScriptValue) {
-			ScriptDebugModelPresentation presentation = DLTKDebugUIPlugin.getDefault()
-					.getModelPresentation(value.getModelIdentifier());
+			ScriptDebugModelPresentation presentation = DLTKDebugUIPlugin
+					.getDefault().getModelPresentation(
+							value.getModelIdentifier());
 			return presentation.getDetailPaneText((IScriptValue) value);
 		}
 		return null;
@@ -89,6 +102,11 @@
 				DetailFormatter formatter = getDetailFormatter(value);
 				if (thread == null || !thread.isSuspended()
 						|| formatter == null || !formatter.isEnabled()) {
+					/*
+					 * if the client doesn't define a formatter, or the engine
+					 * doesn't support the 'eval' command, fall back to using
+					 * the value returned in the 'property' response
+					 */
 					listener.detailComputed(value, getValueText(value));
 				} else {
 					final IScriptEvaluationCommand command = value
@@ -127,7 +145,7 @@
 		DebugPlugin.getDefault().asyncExec(postEventDispatch);
 	}
 
-	protected DetailFormatter getDetailFormatter(IScriptValue value) {
+	public DetailFormatter getDetailFormatter(IScriptValue value) {
 		DetailFormatter formatter = (DetailFormatter) formatters.get(value
 				.getType().getName());
 		if (formatter == null)
@@ -150,4 +168,48 @@
 	public void removeFormatter(DetailFormatter formatter) {
 		formatters.remove(formatter.getTypeName());
 	}
+
+	public void propertyChange(PropertyChangeEvent event) {
+		String property = event.getProperty();
+		if (handlesPropertyEvent(property)) {
+			// TODO: uncomment when supported
+			// populateDetailFormatters(natureId);
+			// cacheMap.clear();
+
+			/*
+			 * fire a change event on it so the variables view will update for
+			 * any formatter changes.
+			 */
+			IAdaptable selected = DebugUITools.getDebugContext();
+			if (selected != null) {
+				IScriptStackFrame frame = (IScriptStackFrame) selected
+						.getAdapter(IScriptStackFrame.class);
+				if (frame != null) {
+					DebugPlugin.getDefault().fireDebugEventSet(
+							new DebugEvent[] { new DebugEvent(frame,
+									DebugEvent.CHANGE) });
+				}
+			}
+		}
+	}
+
+	private boolean handlesPropertyEvent(String property) {
+		// TODO: uncomment when supported
+		// if
+		// (IDLTKDebugUIPreferenceConstants.PREF_DETAIL_FORMATTERS_LIST.equals
+		// (property)) {
+		// return true;
+		// }
+
+		if (IDLTKDebugUIPreferenceConstants.PREF_SHOW_DETAILS.equals(property)) {
+			return true;
+		}
+
+		if (IDebugUIConstants.PREF_MAX_DETAIL_LENGTH.equals(property)) {
+			return true;
+		}
+
+		return false;
+	}
+
 }
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/variables/ScriptVariableLabelProvider.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/variables/ScriptVariableLabelProvider.java
new file mode 100644
index 0000000..968b44c
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/internal/debug/ui/variables/ScriptVariableLabelProvider.java
@@ -0,0 +1,43 @@
+package org.eclipse.dltk.internal.debug.ui.variables;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.debug.internal.ui.model.elements.VariableLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+public class ScriptVariableLabelProvider extends VariableLabelProvider
+		implements IPropertyChangeListener {
+
+	private IPreferenceStore store;
+
+	public ScriptVariableLabelProvider(IPreferenceStore store) {
+		this.store = store;
+		this.store.addPropertyChangeListener(this);
+	}
+
+	public void dispose() {
+		store.removePropertyChangeListener(this);
+		store = null;
+	}
+
+	protected String getValueText(IVariable variable, IValue value,
+			IPresentationContext context) throws CoreException {
+		IDebugModelPresentation presentation = getModelPresentation(context,
+				value.getModelIdentifier());
+		if (presentation != null) {
+			return presentation.getText(value);
+		}
+
+		return super.getValueText(variable, value, context);
+	}
+
+	public void propertyChange(PropertyChangeEvent event) {
+		// TODO: support for fq name vs 'last segment'
+	}
+
+}