blob: a8d76d4516affb58120d879e8f1268a108edf745 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2012 Wind River Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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<>(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.
// Note: Index should be calculated when the IExpressionListener.expressionsAdded
// is called. If it's not, try to calculate it here based on parent count.
int parentCount = parentDelta.getChildCount();
if (elementIdx == -1 && parentCount > 1) {
elementIdx = parentCount - 2;
}
parentDelta.addNode(element, elementIdx, 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();
}
}