blob: 21ceb241babddd8e6a805e60c88950a3ee88f506 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.xdebugger.impl.ui.tree.nodes;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
import com.intellij.xdebugger.frame.XValue;
import com.intellij.xdebugger.impl.frame.WatchInplaceEditor;
import com.intellij.xdebugger.impl.frame.XWatchesView;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreeNode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author nik
*/
public class WatchesRootNode extends XDebuggerTreeNode {
private final XDebugSession mySession;
private final XWatchesView myWatchesView;
private List<WatchNode> myChildren;
private List<XDebuggerTreeNode> myLoadedChildren;
private XDebuggerEvaluator myCurrentEvaluator;
public WatchesRootNode(final @NotNull XDebuggerTree tree,
@NotNull XDebugSession session,
@NotNull XWatchesView watchesView,
@NotNull String[] watchExpressions) {
super(tree, null, false);
mySession = session;
myWatchesView = watchesView;
myChildren = new ArrayList<WatchNode>();
for (String watchExpression : watchExpressions) {
myChildren.add(WatchMessageNode.createMessageNode(tree, this, watchExpression));
}
}
public void updateWatches(@Nullable XDebuggerEvaluator evaluator) {
myCurrentEvaluator = evaluator;
List<WatchNode> newChildren = new ArrayList<WatchNode>();
if (evaluator != null) {
for (WatchNode child : myChildren) {
final String expression = child.getExpression();
final WatchMessageNode evaluatingNode = WatchMessageNode.createEvaluatingNode(myTree, this, expression);
newChildren.add(evaluatingNode);
evaluator.evaluate(expression, new MyEvaluationCallback(evaluatingNode), null);
}
}
else {
for (WatchNode child : myChildren) {
final String expression = child.getExpression();
newChildren.add(WatchMessageNode.createMessageNode(myTree, this, expression));
}
}
myChildren = newChildren;
myLoadedChildren = null;
fireNodeStructureChanged();
}
@NotNull
@Override
public List<? extends TreeNode> getChildren() {
return myChildren;
}
@Nullable
public List<? extends WatchNode> getAllChildren() {
return myChildren;
}
@Override
public List<? extends XDebuggerTreeNode> getLoadedChildren() {
if (myLoadedChildren == null) {
myLoadedChildren = new ArrayList<XDebuggerTreeNode>();
for (WatchNode child : myChildren) {
if (child instanceof WatchNodeImpl) {
myLoadedChildren.add((WatchNodeImpl)child);
}
}
}
return myLoadedChildren;
}
@Override
public void clearChildren() {
updateWatches(myCurrentEvaluator);
}
private void replaceNode(final WatchNode oldNode, final WatchNode newNode) {
for (int i = 0; i < myChildren.size(); i++) {
WatchNode child = myChildren.get(i);
if (child == oldNode) {
myChildren.set(i, newNode);
if (newNode instanceof XValueContainerNode<?>) {
myLoadedChildren = null;
fireNodeStructureChanged(newNode);
myTree.childrenLoaded(this, Collections.<XValueContainerNode<?>>singletonList((XValueContainerNode<?>)newNode), false);
}
else {
fireNodeStructureChanged(newNode);
}
return;
}
}
}
public void addWatchExpression(final @Nullable XDebuggerEvaluator evaluator,
final @NotNull String expression,
int index, final boolean navigateToWatchNode) {
WatchMessageNode message = evaluator != null ? WatchMessageNode.createEvaluatingNode(myTree, this, expression) : WatchMessageNode.createMessageNode(myTree, this, expression);
if (index == -1) {
myChildren.add(message);
index = myChildren.size() - 1;
}
else {
myChildren.add(index, message);
}
fireNodeInserted(index);
if (navigateToWatchNode) {
myTree.scrollPathToVisible(message.getPath());
}
if (evaluator != null) {
evaluator.evaluate(expression, new MyEvaluationCallback(message), null);
}
}
private void fireNodeInserted(int index) {
myTree.getTreeModel().nodesWereInserted(this, new int[]{index});
}
@SuppressWarnings("SuspiciousMethodCalls")
public int removeChildNode(XDebuggerTreeNode node) {
int index = myChildren.indexOf(node);
if (index != -1) {
myChildren.remove(node);
myLoadedChildren = null;
fireNodesRemoved(new int[]{index}, new TreeNode[]{node});
}
return index;
}
public void removeChildren(Collection<? extends XDebuggerTreeNode> nodes) {
final int[] indices = getNodesIndices(nodes);
final TreeNode[] removed = getChildNodes(indices);
myChildren.removeAll(nodes);
myLoadedChildren = null;
fireNodesRemoved(indices, removed);
}
public void removeAllChildren() {
myChildren.clear();
myLoadedChildren = null;
fireNodeStructureChanged();
}
public void addNewWatch() {
editWatch(null);
}
public void editWatch(@Nullable WatchNode node) {
WatchNode messageNode = WatchMessageNode.createMessageNode(myTree, this, "");
int index = node != null ? myChildren.indexOf(node) : -1;
if (index == -1) {
myChildren.add(messageNode);
fireNodeInserted(myChildren.size() - 1);
}
else {
myChildren.set(index, messageNode);
fireNodeStructureChanged(messageNode);
}
WatchInplaceEditor editor = new WatchInplaceEditor(this, mySession, myWatchesView, messageNode, "watch", node);
editor.show();
}
private class MyEvaluationCallback extends XEvaluationCallbackBase {
private final WatchNode myResultPlace;
public MyEvaluationCallback(final @NotNull WatchNode resultPlace) {
myResultPlace = resultPlace;
}
@Override
public void evaluated(@NotNull final XValue result) {
DebuggerUIUtil.invokeLater(new Runnable() {
@Override
public void run() {
replaceNode(myResultPlace, new WatchNodeImpl(myTree, WatchesRootNode.this, result, myResultPlace.getExpression()));
}
});
}
@Override
public void errorOccurred(@NotNull final String errorMessage) {
DebuggerUIUtil.invokeLater(new Runnable() {
@Override
public void run() {
replaceNode(myResultPlace, WatchMessageNode.createErrorNode(myTree, WatchesRootNode.this, myResultPlace.getExpression(), errorMessage));
}
});
}
}
}