/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems and others.
* 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.expression;
import java.util.Map;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.ui.viewmodel.DefaultVMModelProxyStrategy;
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.jface.viewers.TreePath;
/**
* The IModelProxy implementation to be used with an expression
* view model provider.
*
* @see ExpressionVMProvider
*/
public class ExpressionVMProviderModelProxyStrategy extends DefaultVMModelProxyStrategy {
public ExpressionVMProviderModelProxyStrategy(ExpressionVMProvider provider, Object rootElement) {
super(provider, rootElement);
}
private ExpressionVMProvider getExpressionVMProvider() {
return (ExpressionVMProvider)getVMProvider();
}
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
final IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(null, expression);
if (matchingNode != null) {
return getNodeDeltaFlagsForExpression(matchingNode, expression, event);
}
return IModelDelta.NO_CHANGE;
}
private int getNodeDeltaFlagsForExpression(IExpressionVMNode node, IExpression expression, Object event) {
int flags = node.getDeltaFlagsForExpression(expression, event);
IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(node, expression);
if (matchingNode != null && !matchingNode.equals(node)) {
flags = flags | getNodeDeltaFlagsForExpression(matchingNode, expression, event);
} else {
// Check the child nodes of this expression node for additional
// delta flags.
for (IVMNode childNode : getVMProvider().getChildVMNodes(node)) {
if (!childNode.equals(node)) {
int childNodeDeltaFlags = getDeltaFlags(childNode, null, event);
if ((childNodeDeltaFlags & IModelDelta.CONTENT) != 0) {
childNodeDeltaFlags &= ~IModelDelta.CONTENT;
childNodeDeltaFlags |= IModelDelta.STATE;
}
flags |= childNodeDeltaFlags;
}
}
}
return flags;
}
public void buildDeltaForExpression(IExpression expression, int expressionElementIdx, Object event,
VMDelta parentDelta, TreePath path, RequestMonitor rm)
{
final IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(null, expression);
if (matchingNode != null) {
buildNodeDeltaForExpression(matchingNode, expression, expressionElementIdx, event,
parentDelta, path, rm);
} else {
rm.done();
}
}
private void buildNodeDeltaForExpression(final IExpressionVMNode node, final IExpression expression,
final int expressionElementIdx, final Object event, final VMDelta parentDelta, final TreePath path,
final RequestMonitor rm)
{
node.buildDeltaForExpression(
expression, expressionElementIdx, event, parentDelta, path,
new RequestMonitor(getVMProvider().getExecutor(), rm) {
@Override
protected void handleSuccess() {
final IExpressionVMNode matchingNode =
getExpressionVMProvider().findNodeToParseExpression(node, expression);
if (matchingNode != null && !matchingNode.equals(node)) {
buildNodeDeltaForExpression(
matchingNode, expression, expressionElementIdx, event, parentDelta, path, rm);
} else {
getExpressionVMProvider().update(new VMExpressionUpdate(
parentDelta, getVMProvider().getPresentationContext(), expression,
new DataRequestMonitor<Object>(getVMProvider().getExecutor(), rm) {
@Override
protected void handleSuccess() {
buildDeltaForExpressionElement(
node, expression, getData(), expressionElementIdx, event, parentDelta, path, rm);
}
@Override
protected void handleErrorOrWarning() {
// Avoid propagating the error to avoid processing the delta by
// all nodes.
rm.done();
}
}));
}
}
});
}
private void buildDeltaForExpressionElement(IExpressionVMNode node, IExpression expression, Object expressionElement,
int expressionElementIdx, Object event, VMDelta parentDelta, TreePath path, RequestMonitor rm)
{
CountingRequestMonitor multiRm = new CountingRequestMonitor(getVMProvider().getExecutor(), rm);
int multiRmCount = 0;
node.buildDeltaForExpressionElement(expressionElement, expressionElementIdx, event, parentDelta, multiRm);
multiRmCount++;
// Find the child nodes that have deltas for the given event.
Map<IVMNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(node, parentDelta, event);
// If no child layout nodes have deltas we can stop here.
if (childNodesWithDeltaFlags.size() != 0) {
callChildNodesToBuildDelta(
node, childNodesWithDeltaFlags,
parentDelta.addNode(expressionElement, expressionElementIdx, IModelDelta.NO_CHANGE),
event, multiRm);
multiRmCount++;
}
if (event instanceof ExpressionsChangedEvent) {
buildDeltaForExpressionsChangedEvent(expressionElement, expressionElementIdx,
(ExpressionsChangedEvent)event, parentDelta, multiRm);
multiRmCount++;
}
multiRm.setDoneCount(multiRmCount);
}
private void buildDeltaForExpressionsChangedEvent(Object element, int elementIdx, ExpressionsChangedEvent event,
VMDelta parentDelta, final RequestMonitor rm)
{
switch (event.getType()) {
case ADDED:
// New expressions are always added one element before last.
// Last element is the "Add new expression" element.
int parentCount = parentDelta.getChildCount();
parentDelta.addNode(element, parentCount > 1 ? parentCount - 2 : -1, IModelDelta.ADDED);
break;
case CHANGED:
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
break;
case MOVED:
parentDelta.addNode(element, -1, IModelDelta.REMOVED);
parentDelta.addNode(element, elementIdx, IModelDelta.INSERTED);
break;
case REMOVED:
parentDelta.addNode(element, -1, IModelDelta.REMOVED);
break;
case INSERTED:
parentDelta.addNode(element, elementIdx, IModelDelta.INSERTED);
break;
default:
break;
}
rm.done();
}
}